1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * Copyright by the Board of Trustees of the University of Illinois.         *
4  * All rights reserved.                                                      *
5  *                                                                           *
6  * This file is part of HDF5.  The full HDF5 copyright notice, including     *
7  * terms governing use, modification, and redistribution, is contained in    *
8  * the COPYING file, which can be found at the root of the source code       *
9  * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases.  *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
14 /* Programmer:  Quincey Koziol <koziol@ncsa.uiuc.ued>
15  *              Friday, May 29, 1998
16  *
17  * Purpose:	Dataspace selection functions.
18  */
19 
20 #include "H5Smodule.h"          /* This source code file is part of the H5S module */
21 
22 
23 #include "H5private.h"		/* Generic Functions			*/
24 #include "H5Dprivate.h"		/* Datasets				*/
25 #include "H5Eprivate.h"		/* Error handling		  	*/
26 #include "H5FLprivate.h"	/* Free Lists                           */
27 #include "H5Iprivate.h"		/* IDs			  		*/
28 #include "H5MMprivate.h"        /* Memory management                    */
29 #include "H5Spkg.h"		/* Dataspaces 				*/
30 #include "H5VMprivate.h"		/* Vector and array functions		*/
31 #include "H5WBprivate.h"        /* Wrapped Buffers                      */
32 
33 /* Local functions */
34 #ifdef LATER
35 static herr_t H5S_select_iter_block(const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end);
36 static htri_t H5S_select_iter_has_next_block(const H5S_sel_iter_t *iter);
37 static herr_t H5S_select_iter_next_block(H5S_sel_iter_t *iter);
38 #endif /* LATER */
39 
40 /* Declare a free list to manage the H5S_sel_iter_t struct */
41 H5FL_DEFINE(H5S_sel_iter_t);
42 
43 /* Declare extern free list to manage sequences of size_t */
44 H5FL_SEQ_EXTERN(size_t);
45 
46 /* Declare extern free list to manage sequences of hsize_t */
47 H5FL_SEQ_EXTERN(hsize_t);
48 
49 
50 
51 /*--------------------------------------------------------------------------
52  NAME
53     H5S_select_offset
54  PURPOSE
55     Set the selection offset for a datapace
56  USAGE
57     herr_t H5S_select_offset(space, offset)
58         H5S_t *space;	        IN/OUT: Dataspace object to set selection offset
59         const hssize_t *offset; IN: Offset to position the selection at
60  RETURNS
61     Non-negative on success/Negative on failure
62  DESCRIPTION
63     Sets the selection offset for the dataspace
64  GLOBAL VARIABLES
65  COMMENTS, BUGS, ASSUMPTIONS
66     Only works for simple dataspaces currently
67  EXAMPLES
68  REVISION LOG
69 --------------------------------------------------------------------------*/
70 herr_t
H5S_select_offset(H5S_t * space,const hssize_t * offset)71 H5S_select_offset(H5S_t *space, const hssize_t *offset)
72 {
73     FUNC_ENTER_NOAPI_NOINIT_NOERR
74 
75     /* Check args */
76     HDassert(space);
77     HDassert(0 < space->extent.rank && space->extent.rank <= H5S_MAX_RANK);
78     HDassert(offset);
79 
80     /* Copy the offset over */
81     HDmemcpy(space->select.offset, offset, sizeof(hssize_t)*space->extent.rank);
82 
83     /* Indicate that the offset was changed */
84     space->select.offset_changed = TRUE;
85 
86     FUNC_LEAVE_NOAPI(SUCCEED)
87 }   /* H5S_select_offset() */
88 
89 
90 /*--------------------------------------------------------------------------
91  NAME
92     H5S_select_copy
93  PURPOSE
94     Copy a selection from one dataspace to another
95  USAGE
96     herr_t H5S_select_copy(dst, src)
97         H5S_t *dst;  OUT: Pointer to the destination dataspace
98         H5S_t *src;  IN: Pointer to the source dataspace
99  RETURNS
100     Non-negative on success/Negative on failure
101  DESCRIPTION
102     Copies all the selection information (include offset) from the source
103     dataspace to the destination dataspace.
104 
105     If the SHARE_SELECTION flag is set, then the selection can be shared
106     between the source and destination dataspaces.  (This should only occur in
107     situations where the destination dataspace will immediately change to a new
108     selection)
109  GLOBAL VARIABLES
110  COMMENTS, BUGS, ASSUMPTIONS
111  EXAMPLES
112  REVISION LOG
113 --------------------------------------------------------------------------*/
114 herr_t
H5S_select_copy(H5S_t * dst,const H5S_t * src,hbool_t share_selection)115 H5S_select_copy (H5S_t *dst, const H5S_t *src, hbool_t share_selection)
116 {
117     herr_t ret_value = FAIL;    /* Return value */
118 
119     FUNC_ENTER_NOAPI(FAIL)
120 
121     /* Check args */
122     HDassert(dst);
123     HDassert(src);
124 
125     /* Copy regular fields */
126     dst->select=src->select;
127 
128     /* Perform correct type of copy based on the type of selection */
129     if((ret_value=(*src->select.type->copy)(dst,src,share_selection))<0)
130         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy selection specific information")
131 
132 done:
133     FUNC_LEAVE_NOAPI(ret_value)
134 }   /* H5S_select_copy() */
135 
136 
137 /*-------------------------------------------------------------------------
138  * Function:	H5S_select_release
139  *
140  * Purpose:	Releases all memory associated with a dataspace selection.
141  *
142  * Return:	Non-negative on success/Negative on failure
143  *
144  * Programmer:	Quincey Koziol
145  *		Friday, May 30, 2003
146  *
147  * Note: This routine participates in the "Inlining C function pointers"
148  *      pattern, don't call it directly, use the appropriate macro
149  *      defined in H5Sprivate.h.
150  *
151  * Modifications:
152  *
153  *-------------------------------------------------------------------------
154  */
155 herr_t
H5S_select_release(H5S_t * ds)156 H5S_select_release(H5S_t *ds)
157 {
158     herr_t ret_value = FAIL;    /* Return value */
159 
160     FUNC_ENTER_NOAPI_NOINIT_NOERR
161 
162     HDassert(ds);
163 
164     /* Call the selection type's release function */
165     ret_value=(*ds->select.type->release)(ds);
166 
167     FUNC_LEAVE_NOAPI(ret_value)
168 }   /* end H5S_select_release() */
169 
170 
171 /*-------------------------------------------------------------------------
172  * Function:	H5S_select_get_seq_list
173  *
174  * Purpose:	Retrieves the next sequence of offset/length pairs for an
175  *              iterator on a dataspace
176  *
177  * Return:	Non-negative on success/Negative on failure
178  *
179  * Programmer:	Quincey Koziol
180  *		Tuesday, May 18, 2004
181  *
182  * Note: This routine participates in the "Inlining C function pointers"
183  *      pattern, don't call it directly, use the appropriate macro
184  *      defined in H5Sprivate.h.
185  *
186  * Modifications:
187  *
188  *-------------------------------------------------------------------------
189  */
190 herr_t
H5S_select_get_seq_list(const H5S_t * space,unsigned flags,H5S_sel_iter_t * iter,size_t maxseq,size_t maxbytes,size_t * nseq,size_t * nbytes,hsize_t * off,size_t * len)191 H5S_select_get_seq_list(const H5S_t *space, unsigned flags,
192     H5S_sel_iter_t *iter, size_t maxseq, size_t maxbytes,
193     size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len)
194 {
195     herr_t ret_value = FAIL;    /* Return value */
196 
197     FUNC_ENTER_NOAPI_NOINIT_NOERR
198 
199     HDassert(space);
200 
201     /* Call the selection type's get_seq_list function */
202     ret_value = (*space->select.type->get_seq_list)(space, flags, iter, maxseq, maxbytes, nseq, nbytes, off, len);
203 
204     FUNC_LEAVE_NOAPI(ret_value)
205 }   /* end H5S_select_get_seq_list() */
206 
207 
208 /*-------------------------------------------------------------------------
209  * Function:	H5S_select_serial_size
210  *
211  * Purpose:	Determines the number of bytes required to store the current
212  *              selection
213  *
214  * Return:	Non-negative on success/Negative on failure
215  *
216  * Programmer:	Quincey Koziol
217  *		Tuesday, May 18, 2004
218  *
219  * Note: This routine participates in the "Inlining C function pointers"
220  *      pattern, don't call it directly, use the appropriate macro
221  *      defined in H5Sprivate.h.
222  *
223  * Modifications:
224  *
225  *-------------------------------------------------------------------------
226  */
227 hssize_t
H5S_select_serial_size(const H5S_t * space)228 H5S_select_serial_size(const H5S_t *space)
229 {
230     hssize_t ret_value = -1;   /* Return value */
231 
232     FUNC_ENTER_NOAPI_NOINIT_NOERR
233 
234     HDassert(space);
235 
236     /* Call the selection type's serial_size function */
237     ret_value=(*space->select.type->serial_size)(space);
238 
239     FUNC_LEAVE_NOAPI(ret_value)
240 }   /* end H5S_select_serial_size() */
241 
242 
243 /*--------------------------------------------------------------------------
244  NAME
245     H5S_select_serialize
246  PURPOSE
247     Serialize the selection for a dataspace into a buffer
248  USAGE
249     herr_t H5S_select_serialize(space, p)
250         const H5S_t *space;     IN: Dataspace with selection to serialize
251         uint8_t **p;            OUT: Pointer to buffer to put serialized
252                                 selection.  Will be advanced to end of
253                                 serialized selection.
254  RETURNS
255     Non-negative on success/Negative on failure
256  DESCRIPTION
257     Calls the appropriate dataspace selection callback to serialize the
258     current selection into a buffer.
259  GLOBAL VARIABLES
260  COMMENTS, BUGS, ASSUMPTIONS
261     This routine participates in the "Inlining C function pointers"
262         pattern, don't call it directly, use the appropriate macro
263         defined in H5Sprivate.h.
264  EXAMPLES
265  REVISION LOG
266 --------------------------------------------------------------------------*/
267 herr_t
H5S_select_serialize(const H5S_t * space,uint8_t ** p)268 H5S_select_serialize(const H5S_t *space, uint8_t **p)
269 {
270     herr_t ret_value=SUCCEED;   /* Return value */
271 
272     FUNC_ENTER_NOAPI_NOINIT_NOERR
273 
274     HDassert(space);
275     HDassert(p);
276 
277     /* Call the selection type's serialize function */
278     ret_value=(*space->select.type->serialize)(space,p);
279 
280     FUNC_LEAVE_NOAPI(ret_value)
281 }   /* end H5S_select_serialize() */
282 
283 
284 /*--------------------------------------------------------------------------
285  NAME
286     H5Sget_select_npoints
287  PURPOSE
288     Get the number of elements in current selection
289  USAGE
290     hssize_t H5Sget_select_npoints(dsid)
291         hid_t dsid;             IN: Dataspace ID of selection to query
292  RETURNS
293     Non-negative on success/Negative on failure
294  DESCRIPTION
295     Returns the number of elements in current selection for dataspace.
296  GLOBAL VARIABLES
297  COMMENTS, BUGS, ASSUMPTIONS
298  EXAMPLES
299  REVISION LOG
300 --------------------------------------------------------------------------*/
301 hssize_t
H5Sget_select_npoints(hid_t spaceid)302 H5Sget_select_npoints(hid_t spaceid)
303 {
304     H5S_t *space;               /* Dataspace to modify selection of */
305     hssize_t ret_value;         /* return value */
306 
307     FUNC_ENTER_API(FAIL)
308     H5TRACE1("Hs", "i", spaceid);
309 
310     /* Check args */
311     if(NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE)))
312         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
313 
314     ret_value = (hssize_t)H5S_GET_SELECT_NPOINTS(space);
315 
316 done:
317     FUNC_LEAVE_API(ret_value)
318 }   /* H5Sget_select_npoints() */
319 
320 
321 /*--------------------------------------------------------------------------
322  NAME
323     H5S_get_select_npoints
324  PURPOSE
325     Get the number of elements in current selection
326  USAGE
327     hssize_t H5Sget_select_npoints(space)
328         H5S_t *space;             IN: Dataspace of selection to query
329  RETURNS
330     The number of elements in selection on success, 0 on failure
331  DESCRIPTION
332     Returns the number of elements in current selection for dataspace.
333  GLOBAL VARIABLES
334  COMMENTS, BUGS, ASSUMPTIONS
335      This routine participates in the "Inlining C function pointers"
336         pattern, don't call it directly, use the appropriate macro
337         defined in H5Sprivate.h.
338  EXAMPLES
339  REVISION LOG
340 --------------------------------------------------------------------------*/
341 hssize_t
H5S_get_select_npoints(const H5S_t * space)342 H5S_get_select_npoints(const H5S_t *space)
343 {
344     FUNC_ENTER_NOAPI_NOINIT_NOERR
345 
346     /* Check args */
347     HDassert(space);
348 
349     FUNC_LEAVE_NOAPI((hssize_t)space->select.num_elem)
350 }   /* H5S_get_select_npoints() */
351 
352 
353 /*--------------------------------------------------------------------------
354  NAME
355     H5Sselect_valid
356  PURPOSE
357     Check whether the selection fits within the extent, with the current
358     offset defined.
359  USAGE
360     htri_t H5Sselect_void(dsid)
361         hid_t dsid;             IN: Dataspace ID to query
362  RETURNS
363     TRUE if the selection fits within the extent, FALSE if it does not and
364         Negative on an error.
365  DESCRIPTION
366     Determines if the current selection at the current offet fits within the
367     extent for the dataspace.
368  GLOBAL VARIABLES
369  COMMENTS, BUGS, ASSUMPTIONS
370  EXAMPLES
371  REVISION LOG
372     Christian Chilan 01/17/2007
373     Changed the error return value from 0 to FAIL.
374 --------------------------------------------------------------------------*/
375 htri_t
H5Sselect_valid(hid_t spaceid)376 H5Sselect_valid(hid_t spaceid)
377 {
378     H5S_t *space;       /* Dataspace to modify selection of */
379     htri_t ret_value;   /* return value */
380 
381     FUNC_ENTER_API(FAIL)
382     H5TRACE1("t", "i", spaceid);
383 
384     /* Check args */
385     if(NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE)))
386         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
387 
388     ret_value = H5S_SELECT_VALID(space);
389 
390 done:
391     FUNC_LEAVE_API(ret_value)
392 }   /* H5Sselect_valid() */
393 
394 
395 /*--------------------------------------------------------------------------
396  NAME
397     H5S_select_valid
398  PURPOSE
399     Check whether the selection fits within the extent, with the current
400     offset defined.
401  USAGE
402     htri_t H5S_select_void(space)
403         H5S_t *space;           IN: Dataspace to query
404  RETURNS
405     TRUE if the selection fits within the extent, FALSE if it does not and
406         Negative on an error.
407  DESCRIPTION
408     Determines if the current selection at the current offet fits within the
409     extent for the dataspace.
410  GLOBAL VARIABLES
411  COMMENTS, BUGS, ASSUMPTIONS
412      This routine participates in the "Inlining C function pointers"
413         pattern, don't call it directly, use the appropriate macro
414         defined in H5Sprivate.h.
415  EXAMPLES
416  REVISION LOG
417 --------------------------------------------------------------------------*/
418 htri_t
H5S_select_valid(const H5S_t * space)419 H5S_select_valid(const H5S_t *space)
420 {
421     htri_t ret_value = FAIL;    /* Return value */
422 
423     FUNC_ENTER_NOAPI_NOINIT_NOERR
424 
425     HDassert(space);
426 
427     ret_value = (*space->select.type->is_valid)(space);
428 
429     FUNC_LEAVE_NOAPI(ret_value)
430 }   /* H5S_select_valid() */
431 
432 
433 /*--------------------------------------------------------------------------
434  NAME
435     H5S_select_deserialize
436  PURPOSE
437     Deserialize the current selection from a user-provided buffer into a real
438         selection in the dataspace.
439  USAGE
440     herr_t H5S_select_deserialize(space, p)
441         H5S_t **space;          IN/OUT: Dataspace pointer to place
442                                 selection into.  Will be allocated if not
443                                 provided.
444         uint8 **p;              OUT: Pointer to buffer holding serialized
445                                 selection.  Will be advanced to end of
446                                 serialized selection.
447  RETURNS
448     Non-negative on success/Negative on failure
449  DESCRIPTION
450     Deserializes the current selection into a buffer.  (Primarily for retrieving
451     from disk).  This routine just hands off to the appropriate routine for each
452     type of selection.  The format of the serialized information is shown in
453     the H5S_select_serialize() header.
454  GLOBAL VARIABLES
455  COMMENTS, BUGS, ASSUMPTIONS
456  EXAMPLES
457  REVISION LOG
458 --------------------------------------------------------------------------*/
459 herr_t
H5S_select_deserialize(H5S_t ** space,const uint8_t ** p)460 H5S_select_deserialize(H5S_t **space, const uint8_t **p)
461 {
462     H5S_t *tmp_space = NULL;    /* Pointer to actual dataspace to use, either
463                                  *space or a newly allocated one */
464     uint32_t sel_type;          /* Pointer to the selection type */
465     uint32_t version;           /* Version number */
466     uint8_t flags = 0;          /* Flags */
467     herr_t ret_value = FAIL;    /* Return value */
468 
469     FUNC_ENTER_NOAPI(FAIL)
470 
471     HDassert(space);
472 
473     /* Allocate space if not provided */
474     if(!*space) {
475         if(NULL == (tmp_space = H5S_create(H5S_SIMPLE)))
476             HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create dataspace")
477     } /* end if */
478     else
479         tmp_space = *space;
480 
481     /* Decode selection type */
482     UINT32DECODE(*p, sel_type);
483 
484     /* Decode version */
485     UINT32DECODE(*p, version);
486 
487     if(version >= (uint32_t)2) {
488         /* Decode flags */
489         flags = *(*p)++;
490 
491         /* Check for unknown flags */
492         if(flags & ~H5S_SELECT_FLAG_BITS)
493             HGOTO_ERROR(H5E_DATASPACE, H5E_CANTLOAD, FAIL, "unknown flag for selection")
494 
495         /* Skip over the remainder of the header */
496         *p += 4;
497     } /* end if */
498     else
499         /* Skip over the remainder of the header */
500         *p += 8;
501 
502     /* Decode and check or patch rank for point and hyperslab selections */
503     if((sel_type == H5S_SEL_POINTS) || (sel_type == H5S_SEL_HYPERSLABS)) {
504         uint32_t rank;              /* Rank of dataspace */
505 
506         /* Decode the rank of the point selection */
507         UINT32DECODE(*p,rank);
508 
509         if(!*space) {
510             hsize_t dims[H5S_MAX_RANK];
511 
512             /* Patch the rank of the allocated dataspace */
513             (void)HDmemset(dims, 0, (size_t)rank * sizeof(dims[0]));
514             if(H5S_set_extent_simple(tmp_space, rank, dims, NULL) < 0)
515                 HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't set dimensions")
516         } /* end if */
517         else
518             /* Verify the rank of the provided dataspace */
519             if(rank != tmp_space->extent.rank)
520                 HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "rank of serialized selection does not match dataspace")
521     } /* end if */
522 
523     /* Make routine for selection type */
524     switch(sel_type) {
525         case H5S_SEL_POINTS:         /* Sequence of points selected */
526             ret_value = (*H5S_sel_point->deserialize)(tmp_space, version, flags, p);
527             break;
528 
529         case H5S_SEL_HYPERSLABS:     /* Hyperslab selection defined */
530             ret_value = (*H5S_sel_hyper->deserialize)(tmp_space, version, flags, p);
531             break;
532 
533         case H5S_SEL_ALL:            /* Entire extent selected */
534             ret_value = (*H5S_sel_all->deserialize)(tmp_space, version, flags, p);
535             break;
536 
537         case H5S_SEL_NONE:           /* Nothing selected */
538             ret_value = (*H5S_sel_none->deserialize)(tmp_space, version, flags, p);
539             break;
540 
541         default:
542             break;
543     }
544     if(ret_value < 0)
545         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTLOAD, FAIL, "can't deserialize selection")
546 
547     /* Return space to the caller if allocated */
548     if(!*space)
549         *space = tmp_space;
550 
551 done:
552     /* Free temporary space if not passed to caller (only happens on error) */
553     if(!*space && tmp_space)
554         if(H5S_close(tmp_space) < 0)
555             HDONE_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "can't close dataspace")
556 
557     FUNC_LEAVE_NOAPI(ret_value)
558 }   /* H5S_select_deserialize() */
559 
560 
561 /*--------------------------------------------------------------------------
562  NAME
563     H5Sget_select_bounds
564  PURPOSE
565     Gets the bounding box containing the selection.
566  USAGE
567     herr_t H5S_get_select_bounds(space, start, end)
568         hid_t dsid;             IN: Dataspace ID of selection to query
569         hsize_t start[];        OUT: Starting coordinate of bounding box
570         hsize_t end[];          OUT: Opposite coordinate of bounding box
571  RETURNS
572     Non-negative on success, negative on failure
573  DESCRIPTION
574     Retrieves the bounding box containing the current selection and places
575     it into the user's buffers.  The start and end buffers must be large
576     enough to hold the dataspace rank number of coordinates.  The bounding box
577     exactly contains the selection, ie. if a 2-D element selection is currently
578     defined with the following points: (4,5), (6,8) (10,7), the bounding box
579     with be (4, 5), (10, 8).  Calling this function on a "none" selection
580     returns fail.
581         The bounding box calculations _does_ include the current offset of the
582     selection within the dataspace extent.
583  GLOBAL VARIABLES
584  COMMENTS, BUGS, ASSUMPTIONS
585     This routine participates in the "Inlining C function pointers"
586         pattern, don't call it directly, use the appropriate macro
587         defined in H5Sprivate.h.
588  EXAMPLES
589  REVISION LOG
590 --------------------------------------------------------------------------*/
591 herr_t
H5Sget_select_bounds(hid_t spaceid,hsize_t start[],hsize_t end[])592 H5Sget_select_bounds(hid_t spaceid, hsize_t start[], hsize_t end[])
593 {
594     H5S_t *space;       /* Dataspace to modify selection of */
595     herr_t ret_value;   /* return value */
596 
597     FUNC_ENTER_API(FAIL)
598     H5TRACE3("e", "i*h*h", spaceid, start, end);
599 
600     /* Check args */
601     if(start == NULL || end == NULL)
602         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid pointer")
603     if(NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE)))
604         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
605 
606     ret_value = H5S_SELECT_BOUNDS(space, start, end);
607 
608 done:
609     FUNC_LEAVE_API(ret_value)
610 }   /* H5Sget_select_bounds() */
611 
612 
613 /*--------------------------------------------------------------------------
614  NAME
615     H5S_get_select_bounds
616  PURPOSE
617     Gets the bounding box containing the selection.
618  USAGE
619     herr_t H5S_get_select_bounds(space, start, end)
620         H5S_t *space;           IN: Dataspace ID of selection to query
621         hsize_t *start;         OUT: Starting coordinate of bounding box
622         hsize_t *end;           OUT: Opposite coordinate of bounding box
623  RETURNS
624     Non-negative on success, negative on failure
625  DESCRIPTION
626     Retrieves the bounding box containing the current selection and places
627     it into the user's buffers.  The start and end buffers must be large
628     enough to hold the dataspace rank number of coordinates.  The bounding box
629     exactly contains the selection, ie. if a 2-D element selection is currently
630     defined with the following points: (4,5), (6,8) (10,7), the bounding box
631     with be (4, 5), (10, 8).  Calling this function on a "none" selection
632     returns fail.
633         The bounding box calculations _does_ include the current offset of the
634     selection within the dataspace extent.
635  GLOBAL VARIABLES
636  COMMENTS, BUGS, ASSUMPTIONS
637  EXAMPLES
638  REVISION LOG
639 --------------------------------------------------------------------------*/
640 herr_t
H5S_get_select_bounds(const H5S_t * space,hsize_t * start,hsize_t * end)641 H5S_get_select_bounds(const H5S_t *space, hsize_t *start, hsize_t *end)
642 {
643     herr_t ret_value = FAIL;    /* Return value */
644 
645     FUNC_ENTER_NOAPI_NOINIT_NOERR
646 
647     /* Check args */
648     HDassert(space);
649     HDassert(start);
650     HDassert(end);
651 
652     ret_value = (*space->select.type->bounds)(space,start,end);
653 
654     FUNC_LEAVE_NOAPI(ret_value)
655 }   /* H5S_get_select_bounds() */
656 
657 
658 /*--------------------------------------------------------------------------
659  NAME
660     H5S_get_select_offset
661  PURPOSE
662     Gets the linear offset of the first element for the selection.
663  USAGE
664     herr_t H5S_get_select_offset(space, offset)
665         const H5S_t *space;     IN: Dataspace pointer of selection to query
666         hsize_t *offset;        OUT: Linear offset of first element in selection
667  RETURNS
668     Non-negative on success, negative on failure
669  DESCRIPTION
670     Retrieves the linear offset (in "units" of elements) of the first element
671     selected within the dataspace.
672  GLOBAL VARIABLES
673  COMMENTS, BUGS, ASSUMPTIONS
674         The offset calculation _does_ include the current offset of the
675     selection within the dataspace extent.
676 
677         Calling this function on a "none" selection returns fail.
678  EXAMPLES
679  REVISION LOG
680 --------------------------------------------------------------------------*/
681 herr_t
H5S_get_select_offset(const H5S_t * space,hsize_t * offset)682 H5S_get_select_offset(const H5S_t *space, hsize_t *offset)
683 {
684     herr_t ret_value = FAIL;    /* Return value */
685 
686     FUNC_ENTER_NOAPI_NOINIT_NOERR
687 
688     /* Check args */
689     HDassert(space);
690     HDassert(offset);
691 
692     ret_value = (*space->select.type->offset)(space, offset);
693 
694     FUNC_LEAVE_NOAPI(ret_value)
695 }   /* H5S_get_select_offset() */
696 
697 
698 /*--------------------------------------------------------------------------
699  NAME
700     H5S_get_select_unlim_dim
701  PURPOSE
702     Gets the unlimited dimension in the selection, or -1 if there is no
703     unlimited dimension.
704  USAGE
705     int H5S_get_select_unlim_dim(space)
706         const H5S_t *space;     IN: Dataspace pointer of selection to query
707  RETURNS
708     Unlimited dimension in the selection, or -1 if there is no unlimited
709     dimension (never fails)
710  DESCRIPTION
711     Gets the unlimited dimension in the selection, or -1 if there is no
712     unlimited dimension.
713  GLOBAL VARIABLES
714  COMMENTS, BUGS, ASSUMPTIONS
715         Currently only implemented for hyperslab selections, all others
716         simply return -1.
717  EXAMPLES
718  REVISION LOG
719 --------------------------------------------------------------------------*/
720 int
H5S_get_select_unlim_dim(const H5S_t * space)721 H5S_get_select_unlim_dim(const H5S_t *space)
722 {
723     herr_t ret_value = FAIL;    /* Return value */
724 
725     FUNC_ENTER_NOAPI_NOINIT_NOERR
726 
727     /* Check args */
728     HDassert(space);
729 
730     ret_value = (*space->select.type->unlim_dim)(space);
731 
732     FUNC_LEAVE_NOAPI(ret_value)
733 }   /* H5S_get_select_unlim_dim() */
734 
735 
736 /*--------------------------------------------------------------------------
737  NAME
738     H5S_get_select_num_elem_non_unlim
739  PURPOSE
740     Gets the number of elements in the non-unlimited dimensions
741  USAGE
742     herr_t H5S_get_select_num_elem_non_unlim(space,num_elem_non_unlim)
743         H5S_t *space;           IN: Dataspace pointer to check
744         hsize_t *num_elem_non_unlim; OUT: Number of elements in the non-unlimited dimensions
745  RETURNS
746     Non-negative on success/Negative on failure
747  DESCRIPTION
748     Returns the number of elements in a slice through the non-unlimited
749     dimensions of the selection.  Fails if the selection has no unlimited
750     dimension.
751  GLOBAL VARIABLES
752  COMMENTS, BUGS, ASSUMPTIONS
753  EXAMPLES
754  REVISION LOG
755 --------------------------------------------------------------------------*/
756 herr_t
H5S_get_select_num_elem_non_unlim(const H5S_t * space,hsize_t * num_elem_non_unlim)757 H5S_get_select_num_elem_non_unlim(const H5S_t *space,
758     hsize_t *num_elem_non_unlim)
759 {
760     herr_t ret_value = SUCCEED; /* return value */
761 
762     FUNC_ENTER_NOAPI(FAIL)
763 
764     /* Check args */
765     HDassert(space);
766     HDassert(num_elem_non_unlim);
767 
768     /* Check for selection callback */
769     if(!space->select.type->num_elem_non_unlim)
770         HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "selection type has no num_elem_non_unlim callback")
771 
772     /* Make selection callback */
773     if((*space->select.type->num_elem_non_unlim)(space, num_elem_non_unlim) < 0)
774         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't get number of elements in non-unlimited dimension")
775 
776 done:
777     FUNC_LEAVE_NOAPI(ret_value)
778 }   /* H5S_get_select_unlim_dim() */
779 
780 
781 /*--------------------------------------------------------------------------
782  NAME
783     H5S_select_is_contiguous
784  PURPOSE
785     Determines if a selection is contiguous in the dataspace
786  USAGE
787     htri_t H5S_select_is_contiguous(space)
788         const H5S_t *space;             IN: Dataspace of selection to query
789  RETURNS
790     Non-negative (TRUE/FALSE) on success, negative on failure
791  DESCRIPTION
792     Checks the selection to determine if the points to iterated over will be
793     contiguous in the particular dataspace.
794  GLOBAL VARIABLES
795  COMMENTS, BUGS, ASSUMPTIONS
796     This routine participates in the "Inlining C function pointers"
797         pattern, don't call it directly, use the appropriate macro
798         defined in H5Sprivate.h.
799  EXAMPLES
800  REVISION LOG
801 --------------------------------------------------------------------------*/
802 htri_t
H5S_select_is_contiguous(const H5S_t * space)803 H5S_select_is_contiguous(const H5S_t *space)
804 {
805     herr_t ret_value = FAIL;    /* Return value */
806 
807     FUNC_ENTER_NOAPI_NOINIT_NOERR
808 
809     /* Check args */
810     HDassert(space);
811 
812     ret_value = (*space->select.type->is_contiguous)(space);
813 
814     FUNC_LEAVE_NOAPI(ret_value)
815 }   /* H5S_select_is_contiguous() */
816 
817 
818 /*--------------------------------------------------------------------------
819  NAME
820     H5S_select_is_single
821  PURPOSE
822     Determines if a selection is a single block in the dataspace
823  USAGE
824     htri_t H5S_select_is_single(space)
825         const H5S_t *space;             IN: Dataspace of selection to query
826  RETURNS
827     Non-negative (TRUE/FALSE) on success, negative on failure
828  DESCRIPTION
829     Checks the selection to determine if it occupies a single block in the
830     particular dataspace.
831  GLOBAL VARIABLES
832  COMMENTS, BUGS, ASSUMPTIONS
833     This routine participates in the "Inlining C function pointers"
834         pattern, don't call it directly, use the appropriate macro
835         defined in H5Sprivate.h.
836  EXAMPLES
837  REVISION LOG
838 --------------------------------------------------------------------------*/
839 htri_t
H5S_select_is_single(const H5S_t * space)840 H5S_select_is_single(const H5S_t *space)
841 {
842     herr_t ret_value = FAIL;    /* Return value */
843 
844     FUNC_ENTER_NOAPI_NOINIT_NOERR
845 
846     /* Check args */
847     HDassert(space);
848 
849     ret_value = (*space->select.type->is_single)(space);
850 
851     FUNC_LEAVE_NOAPI(ret_value)
852 }   /* H5S_select_is_single() */
853 
854 
855 /*--------------------------------------------------------------------------
856  NAME
857     H5S_select_is_regular
858  PURPOSE
859     Determines if a selection is "regular"  in the dataspace
860  USAGE
861     htri_t H5S_select_is_regular(space)
862         const H5S_t *space;             IN: Dataspace of selection to query
863  RETURNS
864     Non-negative (TRUE/FALSE) on success, negative on failure
865  DESCRIPTION
866     Checks the selection to determine if it is "regular" (i.e. a single
867     block or a strided pattern) in the particular dataspace.
868  GLOBAL VARIABLES
869  COMMENTS, BUGS, ASSUMPTIONS
870     This routine participates in the "Inlining C function pointers"
871         pattern, don't call it directly, use the appropriate macro
872         defined in H5Sprivate.h.
873  EXAMPLES
874  REVISION LOG
875 --------------------------------------------------------------------------*/
876 htri_t
H5S_select_is_regular(const H5S_t * space)877 H5S_select_is_regular(const H5S_t *space)
878 {
879     herr_t ret_value = FAIL;    /* Return value */
880 
881     FUNC_ENTER_NOAPI_NOINIT_NOERR
882 
883     /* Check args */
884     HDassert(space);
885 
886     ret_value = (*space->select.type->is_regular)(space);
887 
888     FUNC_LEAVE_NOAPI(ret_value)
889 }   /* H5S_select_is_regular() */
890 
891 
892 /*--------------------------------------------------------------------------
893  NAME
894     H5S_select_adjust_u
895  PURPOSE
896     Adjust a selection by subtracting an offset
897  USAGE
898     herr_t H5S_select_adjust_u(space, offset)
899         H5S_t *space;           IN/OUT: Pointer to dataspace to adjust
900         const hsize_t *offset; IN: Offset to subtract
901  RETURNS
902     Non-negative on success, negative on failure
903  DESCRIPTION
904     Moves a selection by subtracting an offset from it.
905  GLOBAL VARIABLES
906  COMMENTS, BUGS, ASSUMPTIONS
907     This routine participates in the "Inlining C function pointers"
908         pattern, don't call it directly, use the appropriate macro
909         defined in H5Sprivate.h.
910  EXAMPLES
911  REVISION LOG
912 --------------------------------------------------------------------------*/
913 herr_t
H5S_select_adjust_u(H5S_t * space,const hsize_t * offset)914 H5S_select_adjust_u(H5S_t *space, const hsize_t *offset)
915 {
916     herr_t ret_value = FAIL;    /* Return value */
917 
918     FUNC_ENTER_NOAPI_NOINIT_NOERR
919 
920     /* Check args */
921     HDassert(space);
922 
923     ret_value = (*space->select.type->adjust_u)(space, offset);
924 
925     FUNC_LEAVE_NOAPI(ret_value)
926 }   /* H5S_select_adjust_u() */
927 
928 
929 /*--------------------------------------------------------------------------
930  NAME
931     H5S_select_project_scalar
932  PURPOSE
933     Project a single element selection for a scalar dataspace
934  USAGE
935     herr_t H5S_select_project_scalar(space, offset)
936         const H5S_t *space;             IN: Pointer to dataspace to project
937         hsize_t *offset;                IN/OUT: Offset of projected point
938  RETURNS
939     Non-negative on success, negative on failure
940  DESCRIPTION
941     Projects a selection of a single element into a scalar dataspace, computing
942     the offset of the element in the original selection.
943  GLOBAL VARIABLES
944  COMMENTS, BUGS, ASSUMPTIONS
945     This routine participates in the "Inlining C function pointers"
946         pattern, don't call it directly, use the appropriate macro
947         defined in H5Sprivate.h.
948  EXAMPLES
949  REVISION LOG
950 --------------------------------------------------------------------------*/
951 herr_t
H5S_select_project_scalar(const H5S_t * space,hsize_t * offset)952 H5S_select_project_scalar(const H5S_t *space, hsize_t *offset)
953 {
954     herr_t ret_value = FAIL;    /* Return value */
955 
956     FUNC_ENTER_NOAPI_NOINIT_NOERR
957 
958     /* Check args */
959     HDassert(space);
960     HDassert(offset);
961 
962     ret_value = (*space->select.type->project_scalar)(space, offset);
963 
964     FUNC_LEAVE_NOAPI(ret_value)
965 }   /* H5S_select_project_scalar() */
966 
967 
968 /*--------------------------------------------------------------------------
969  NAME
970     H5S_select_project_simple
971  PURPOSE
972     Project a selection onto/into a dataspace of different rank
973  USAGE
974     herr_t H5S_select_project_simple(space, new_space, offset)
975         const H5S_t *space;             IN: Pointer to dataspace to project
976         H5S_t *new_space;               IN/OUT: Pointer to dataspace projected onto
977         hsize_t *offset;                IN/OUT: Offset of projected point
978  RETURNS
979     Non-negative on success, negative on failure
980  DESCRIPTION
981     Projects a selection onto/into a simple dataspace, computing
982     the offset of the first element in the original selection.
983  GLOBAL VARIABLES
984  COMMENTS, BUGS, ASSUMPTIONS
985     This routine participates in the "Inlining C function pointers"
986         pattern, don't call it directly, use the appropriate macro
987         defined in H5Sprivate.h.
988  EXAMPLES
989  REVISION LOG
990 --------------------------------------------------------------------------*/
991 herr_t
H5S_select_project_simple(const H5S_t * space,H5S_t * new_space,hsize_t * offset)992 H5S_select_project_simple(const H5S_t *space, H5S_t *new_space, hsize_t *offset)
993 {
994     herr_t ret_value = FAIL;    /* Return value */
995 
996     FUNC_ENTER_NOAPI_NOINIT_NOERR
997 
998     /* Check args */
999     HDassert(space);
1000     HDassert(new_space);
1001     HDassert(offset);
1002 
1003     ret_value = (*space->select.type->project_simple)(space, new_space, offset);
1004 
1005     FUNC_LEAVE_NOAPI(ret_value)
1006 }   /* H5S_select_project_simple() */
1007 
1008 
1009 /*--------------------------------------------------------------------------
1010  NAME
1011     H5S_select_iter_init
1012  PURPOSE
1013     Initializes iteration information for a selection.
1014  USAGE
1015     herr_t H5S_select_iter_init(sel_iter, space, elmt_size)
1016         H5S_sel_iter_t *sel_iter; OUT: Selection iterator to initialize.
1017         H5S_t *space;           IN: Dataspace object containing selection to
1018                                     iterate over
1019         size_t elmt_size;       IN: Size of elements in the selection
1020  RETURNS
1021      Non-negative on success, negative on failure.
1022  DESCRIPTION
1023     Initialize the selection iterator object to point to the first element
1024     in the dataspace's selection.
1025 --------------------------------------------------------------------------*/
1026 herr_t
H5S_select_iter_init(H5S_sel_iter_t * sel_iter,const H5S_t * space,size_t elmt_size)1027 H5S_select_iter_init(H5S_sel_iter_t *sel_iter, const H5S_t *space, size_t elmt_size)
1028 {
1029     herr_t ret_value = FAIL;    /* Return value */
1030 
1031     FUNC_ENTER_NOAPI_NOINIT_NOERR
1032 
1033     /* Check args */
1034     HDassert(sel_iter);
1035     HDassert(space);
1036 
1037     /* Initialize common information */
1038 
1039     /* Save the dataspace's rank */
1040     sel_iter->rank = space->extent.rank;
1041 
1042     /* Point to the dataspace dimensions, if there are any */
1043     if(sel_iter->rank > 0)
1044         sel_iter->dims = space->extent.size;
1045     else
1046         sel_iter->dims = NULL;
1047 
1048     /* Save the element size */
1049     sel_iter->elmt_size = elmt_size;
1050 
1051     /* Call initialization routine for selection type */
1052     ret_value = (*space->select.type->iter_init)(sel_iter, space);
1053     HDassert(sel_iter->type);
1054 
1055     FUNC_LEAVE_NOAPI(ret_value)
1056 }   /* H5S_select_iter_init() */
1057 
1058 
1059 /*--------------------------------------------------------------------------
1060  NAME
1061     H5S_select_iter_coords
1062  PURPOSE
1063     Get the coordinates of the current iterator position
1064  USAGE
1065     herr_t H5S_select_iter_coords(sel_iter,coords)
1066         H5S_sel_iter_t *sel_iter; IN: Selection iterator to query
1067         hsize_t *coords;         OUT: Array to place iterator coordinates in
1068  RETURNS
1069     Non-negative on success, negative on failure.
1070  DESCRIPTION
1071     The current location of the iterator within the selection is placed in
1072     the COORDS array.
1073  GLOBAL VARIABLES
1074  COMMENTS, BUGS, ASSUMPTIONS
1075     This routine participates in the "Inlining C function pointers"
1076         pattern, don't call it directly, use the appropriate macro
1077         defined in H5Sprivate.h.
1078  EXAMPLES
1079  REVISION LOG
1080 --------------------------------------------------------------------------*/
1081 herr_t
H5S_select_iter_coords(const H5S_sel_iter_t * sel_iter,hsize_t * coords)1082 H5S_select_iter_coords(const H5S_sel_iter_t *sel_iter, hsize_t *coords)
1083 {
1084     herr_t ret_value = FAIL;    /* Return value */
1085 
1086     FUNC_ENTER_NOAPI_NOINIT_NOERR
1087 
1088     /* Check args */
1089     HDassert(sel_iter);
1090     HDassert(coords);
1091 
1092     /* Call iter_coords routine for selection type */
1093     ret_value = (*sel_iter->type->iter_coords)(sel_iter,coords);
1094 
1095     FUNC_LEAVE_NOAPI(ret_value)
1096 }   /* H5S_select_iter_coords() */
1097 
1098 #ifdef LATER
1099 
1100 /*--------------------------------------------------------------------------
1101  NAME
1102     H5S_select_iter_block
1103  PURPOSE
1104     Get the block of the current iterator position
1105  USAGE
1106     herr_t H5S_select_iter_block(sel_iter,start,end)
1107         const H5S_sel_iter_t *sel_iter; IN: Selection iterator to query
1108         hsize_t *start;    OUT: Array to place iterator start block coordinates
1109         hsize_t *end;      OUT: Array to place iterator end block coordinates
1110  RETURNS
1111     Non-negative on success, negative on failure.
1112  DESCRIPTION
1113     The current location of the iterator within the selection is placed in
1114     the COORDS array.
1115  GLOBAL VARIABLES
1116  COMMENTS, BUGS, ASSUMPTIONS
1117     This routine participates in the "Inlining C function pointers"
1118         pattern, don't call it directly, use the appropriate macro
1119         defined in H5Sprivate.h.
1120  EXAMPLES
1121  REVISION LOG
1122 --------------------------------------------------------------------------*/
1123 static herr_t
H5S_select_iter_block(const H5S_sel_iter_t * iter,hsize_t * start,hsize_t * end)1124 H5S_select_iter_block(const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end)
1125 {
1126     herr_t ret_value;         /* return value */
1127 
1128     FUNC_ENTER_NOAPI_NOINIT_NOINIT_NOERR
1129 
1130     /* Check args */
1131     HDassert(iter);
1132     HDassert(start);
1133     HDassert(end);
1134 
1135     /* Call iter_block routine for selection type */
1136     ret_value = (*iter->type->iter_block)(iter,start,end);
1137 
1138     FUNC_LEAVE_NOAPI(ret_value)
1139 }   /* H5S_select_iter_block() */
1140 #endif /* LATER */
1141 
1142 
1143 /*--------------------------------------------------------------------------
1144  NAME
1145     H5S_select_iter_nelmts
1146  PURPOSE
1147     Get the number of elements left to iterate over in selection
1148  USAGE
1149     hssize_t H5S_select_iter_nelmts(sel_iter)
1150         H5S_sel_iter_t *sel_iter; IN: Selection iterator to query
1151  RETURNS
1152     The number of elements in selection on success, 0 on failure
1153  DESCRIPTION
1154     Returns the number of elements in current selection for dataspace.
1155  GLOBAL VARIABLES
1156  COMMENTS, BUGS, ASSUMPTIONS
1157     This routine participates in the "Inlining C function pointers"
1158         pattern, don't call it directly, use the appropriate macro
1159         defined in H5Sprivate.h.
1160  EXAMPLES
1161  REVISION LOG
1162 --------------------------------------------------------------------------*/
1163 hsize_t
H5S_select_iter_nelmts(const H5S_sel_iter_t * sel_iter)1164 H5S_select_iter_nelmts(const H5S_sel_iter_t *sel_iter)
1165 {
1166     hsize_t ret_value = 0;      /* Return value */
1167 
1168     FUNC_ENTER_NOAPI_NOINIT_NOERR
1169 
1170     /* Check args */
1171     HDassert(sel_iter);
1172 
1173     /* Call iter_nelmts routine for selection type */
1174     ret_value = (*sel_iter->type->iter_nelmts)(sel_iter);
1175 
1176     FUNC_LEAVE_NOAPI(ret_value)
1177 }   /* H5S_select_iter_nelmts() */
1178 
1179 #ifdef LATER
1180 
1181 /*--------------------------------------------------------------------------
1182  NAME
1183     H5S_select_iter_has_next_block
1184  PURPOSE
1185     Check if there is another block available in the selection iterator
1186  USAGE
1187     htri_t H5S_select_iter_has_next_block(sel_iter)
1188         const H5S_sel_iter_t *sel_iter; IN: Selection iterator to query
1189  RETURNS
1190     Non-negative on success, negative on failure.
1191  DESCRIPTION
1192     Check if there is another block available to advance to in the selection
1193     iterator.
1194  GLOBAL VARIABLES
1195  COMMENTS, BUGS, ASSUMPTIONS
1196     This routine participates in the "Inlining C function pointers"
1197         pattern, don't call it directly, use the appropriate macro
1198         defined in H5Sprivate.h.
1199  EXAMPLES
1200  REVISION LOG
1201 --------------------------------------------------------------------------*/
1202 static htri_t
H5S_select_iter_has_next_block(const H5S_sel_iter_t * iter)1203 H5S_select_iter_has_next_block(const H5S_sel_iter_t *iter)
1204 {
1205     herr_t ret_value;         /* return value */
1206 
1207     FUNC_ENTER_NOAPI_NOINIT_NOINIT_NOERR
1208 
1209     /* Check args */
1210     HDassert(iter);
1211 
1212     /* Call iter_has_next_block routine for selection type */
1213     ret_value = (*iter->type->iter_has_next_block)(iter);
1214 
1215     FUNC_LEAVE_NOAPI(ret_value)
1216 }   /* H5S_select_iter_has_next_block() */
1217 #endif /* LATER */
1218 
1219 
1220 /*--------------------------------------------------------------------------
1221  NAME
1222     H5S_select_iter_next
1223  PURPOSE
1224     Advance selection iterator to next element
1225  USAGE
1226     herr_t H5S_select_iter_next(iter, nelem)
1227         H5S_sel_iter_t *iter;   IN/OUT: Selection iterator to change
1228         size_t nelem;           IN: Number of elements to advance by
1229  RETURNS
1230     Non-negative on success, negative on failure.
1231  DESCRIPTION
1232     Move the current element for the selection iterator to the NELEM'th next
1233     element in the selection.
1234  GLOBAL VARIABLES
1235  COMMENTS, BUGS, ASSUMPTIONS
1236     This routine participates in the "Inlining C function pointers"
1237         pattern, don't call it directly, use the appropriate macro
1238         defined in H5Sprivate.h.
1239  EXAMPLES
1240  REVISION LOG
1241 --------------------------------------------------------------------------*/
1242 herr_t
H5S_select_iter_next(H5S_sel_iter_t * iter,size_t nelem)1243 H5S_select_iter_next(H5S_sel_iter_t *iter, size_t nelem)
1244 {
1245     herr_t ret_value = FAIL;    /* Return value */
1246 
1247     FUNC_ENTER_NOAPI_NOINIT_NOERR
1248 
1249     /* Check args */
1250     HDassert(iter);
1251     HDassert(nelem>0);
1252 
1253     /* Call iter_next routine for selection type */
1254     ret_value = (*iter->type->iter_next)(iter,nelem);
1255 
1256     /* Decrement the number of elements left in selection */
1257     iter->elmt_left-=nelem;
1258 
1259     FUNC_LEAVE_NOAPI(ret_value)
1260 }   /* H5S_select_iter_next() */
1261 
1262 #ifdef LATER
1263 
1264 /*--------------------------------------------------------------------------
1265  NAME
1266     H5S_select_iter_next_block
1267  PURPOSE
1268     Advance selection iterator to next block
1269  USAGE
1270     herr_t H5S_select_iter_next_block(iter)
1271         H5S_sel_iter_t *iter;   IN/OUT: Selection iterator to change
1272  RETURNS
1273     Non-negative on success, negative on failure.
1274  DESCRIPTION
1275     Move the current element for the selection iterator to the next
1276     block in the selection.
1277  GLOBAL VARIABLES
1278  COMMENTS, BUGS, ASSUMPTIONS
1279     Doesn't maintain the 'elmt_left' field of the selection iterator.
1280 
1281     This routine participates in the "Inlining C function pointers"
1282         pattern, don't call it directly, use the appropriate macro
1283         defined in H5Sprivate.h.
1284  EXAMPLES
1285  REVISION LOG
1286 --------------------------------------------------------------------------*/
1287 static herr_t
H5S_select_iter_next_block(H5S_sel_iter_t * iter)1288 H5S_select_iter_next_block(H5S_sel_iter_t *iter)
1289 {
1290     herr_t ret_value;         /* return value */
1291 
1292     FUNC_ENTER_NOAPI_NOINIT_NOERR
1293 
1294     /* Check args */
1295     HDassert(iter);
1296 
1297     /* Call iter_next_block routine for selection type */
1298     ret_value = (*iter->type->iter_next_block)(iter);
1299 
1300     FUNC_LEAVE_NOAPI(ret_value)
1301 }   /* H5S_select_iter_next_block() */
1302 #endif /* LATER */
1303 
1304 
1305 /*--------------------------------------------------------------------------
1306  NAME
1307     H5S_select_iter_release
1308  PURPOSE
1309     Release a selection iterator's resources.
1310  USAGE
1311     hssize_t H5S_select_iter_release(sel_iter)
1312         H5S_sel_iter_t *sel_iter; IN: Selection iterator to query
1313  RETURNS
1314     The number of elements in selection on success, 0 on failure
1315  DESCRIPTION
1316     Returns the number of elements in current selection for dataspace.
1317  GLOBAL VARIABLES
1318  COMMENTS, BUGS, ASSUMPTIONS
1319     This routine participates in the "Inlining C function pointers"
1320         pattern, don't call it directly, use the appropriate macro
1321         defined in H5Sprivate.h.
1322  EXAMPLES
1323  REVISION LOG
1324 --------------------------------------------------------------------------*/
1325 herr_t
H5S_select_iter_release(H5S_sel_iter_t * sel_iter)1326 H5S_select_iter_release(H5S_sel_iter_t *sel_iter)
1327 {
1328     herr_t ret_value = FAIL;    /* Return value */
1329 
1330     FUNC_ENTER_NOAPI_NOINIT_NOERR
1331 
1332     /* Check args */
1333     HDassert(sel_iter);
1334 
1335     /* Call selection type-specific release routine */
1336     ret_value = (*sel_iter->type->iter_release)(sel_iter);
1337 
1338     FUNC_LEAVE_NOAPI(ret_value)
1339 }   /* H5S_select_iter_release() */
1340 
1341 
1342 /*--------------------------------------------------------------------------
1343  NAME
1344     H5S_select_iterate
1345  PURPOSE
1346     Iterate over the selected elements in a memory buffer.
1347  USAGE
1348     herr_t H5S_select_iterate(buf, type, space, operator, operator_data)
1349         void *buf;      IN/OUT: Buffer containing elements to iterate over
1350         H5T_t *type;    IN: Datatype of BUF array.
1351         H5S_t *space;   IN: Dataspace object containing selection to iterate over
1352         H5D_operator_t op; IN: Function pointer to the routine to be
1353                                 called for each element in BUF iterated over.
1354         void *operator_data;    IN/OUT: Pointer to any user-defined data
1355                                 associated with the operation.
1356  RETURNS
1357     Returns the return value of the last operator if it was non-zero, or zero
1358     if all elements were processed. Otherwise returns a negative value.
1359  DESCRIPTION
1360     Iterates over the selected elements in a memory buffer, calling the user's
1361     callback function for each element.  The selection in the dataspace is
1362     modified so that any elements already iterated over are removed from the
1363     selection if the iteration is interrupted (by the H5D_operator_t function
1364     returning non-zero) in the "middle" of the iteration and may be re-started
1365     by the user where it left off.
1366 
1367     NOTE: Until "subtracting" elements from a selection is implemented,
1368         the selection is not modified.
1369 --------------------------------------------------------------------------*/
1370 herr_t
H5S_select_iterate(void * buf,const H5T_t * type,const H5S_t * space,const H5S_sel_iter_op_t * op,void * op_data)1371 H5S_select_iterate(void *buf, const H5T_t *type, const H5S_t *space,
1372     const H5S_sel_iter_op_t *op, void *op_data)
1373 {
1374     H5S_sel_iter_t *iter = NULL; /* Selection iteration info */
1375     hbool_t iter_init = FALSE;  /* Selection iteration info has been initialized */
1376     hsize_t *off = NULL;        /* Array to store sequence offsets */
1377     size_t *len = NULL;         /* Array to store sequence lengths */
1378     hssize_t nelmts;            /* Number of elements in selection */
1379     hsize_t space_size[H5O_LAYOUT_NDIMS]; /* Dataspace size */
1380     size_t max_elem;            /* Maximum number of elements allowed in sequences */
1381     size_t elmt_size;           /* Datatype size */
1382     unsigned ndims;             /* Number of dimensions in dataspace */
1383     herr_t user_ret = 0;        /* User's return value */
1384     herr_t ret_value = SUCCEED; /* Return value */
1385 
1386     FUNC_ENTER_NOAPI(FAIL)
1387 
1388     /* Check args */
1389     HDassert(buf);
1390     HDassert(type);
1391     HDassert(space);
1392     HDassert(op);
1393 
1394     /* Get the datatype size */
1395     if(0 == (elmt_size = H5T_get_size(type)))
1396         HGOTO_ERROR(H5E_DATATYPE, H5E_BADSIZE, FAIL, "datatype size invalid")
1397 
1398     /* Allocate the selection iterator */
1399     if(NULL == (iter = H5FL_MALLOC(H5S_sel_iter_t)))
1400         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate selection iterator")
1401 
1402     /* Initialize iterator */
1403     if(H5S_select_iter_init(iter, space, elmt_size) < 0)
1404         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
1405     iter_init = TRUE;	/* Selection iteration info has been initialized */
1406 
1407     /* Get the number of elements in selection */
1408     if((nelmts = (hssize_t)H5S_GET_SELECT_NPOINTS(space)) < 0)
1409         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't get number of elements selected")
1410 
1411     /* Get the rank of the dataspace */
1412     ndims = space->extent.rank;
1413 
1414     if(ndims > 0) {
1415 	/* Copy the size of the space */
1416 	HDassert(space->extent.size);
1417 	HDmemcpy(space_size, space->extent.size, ndims * sizeof(hsize_t));
1418     } /* end if */
1419     space_size[ndims] = elmt_size;
1420 
1421     /* Compute the maximum number of bytes required */
1422     H5_CHECKED_ASSIGN(max_elem, size_t, nelmts, hssize_t);
1423 
1424     /* Allocate the offset & length arrays */
1425     if(NULL == (len = H5FL_SEQ_MALLOC(size_t, H5D_IO_VECTOR_SIZE)))
1426         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate length vector array")
1427     if(NULL == (off = H5FL_SEQ_MALLOC(hsize_t, H5D_IO_VECTOR_SIZE)))
1428         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate offset vector array")
1429 
1430     /* Loop, while elements left in selection */
1431     while(max_elem > 0 && user_ret == 0) {
1432         size_t nelem;               /* Number of elements used in sequences */
1433         size_t nseq;                /* Number of sequences generated */
1434         size_t curr_seq;            /* Current sequence being worked on */
1435 
1436         /* Get the sequences of bytes */
1437         if(H5S_SELECT_GET_SEQ_LIST(space, 0, iter, (size_t)H5D_IO_VECTOR_SIZE, max_elem, &nseq, &nelem, off, len) < 0)
1438             HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed")
1439 
1440         /* Loop, while sequences left to process */
1441         for(curr_seq = 0; curr_seq < nseq && user_ret == 0; curr_seq++) {
1442             hsize_t curr_off;           /* Current offset within sequence */
1443             size_t curr_len;            /* Length of bytes left to process in sequence */
1444 
1445             /* Get the current offset */
1446             curr_off = off[curr_seq];
1447 
1448             /* Get the number of bytes in sequence */
1449             curr_len = len[curr_seq];
1450 
1451             /* Loop, while bytes left in sequence */
1452             while(curr_len > 0 && user_ret == 0) {
1453                 hsize_t coords[H5O_LAYOUT_NDIMS];  /* Coordinates of element in dataspace */
1454                 hsize_t tmp_off;        /* Temporary offset within sequence */
1455                 uint8_t *loc;           /* Current element location in buffer */
1456                 int i;			/* Local Index variable */
1457 
1458                 /* Compute the coordinate from the offset */
1459                 for(i = (int)ndims, tmp_off = curr_off; i >= 0; i--) {
1460                     coords[i] = tmp_off % space_size[i];
1461                     tmp_off /= space_size[i];
1462                 } /* end for */
1463 
1464                 /* Get the location within the user's buffer */
1465                 loc = (unsigned char *)buf + curr_off;
1466 
1467                 /* Check which type of callback to make */
1468                 switch(op->op_type) {
1469                     case H5S_SEL_ITER_OP_APP:
1470                         /* Make the application callback */
1471                         user_ret = (op->u.app_op.op)(loc, op->u.app_op.type_id, ndims, coords, op_data);
1472                     break;
1473                     case H5S_SEL_ITER_OP_LIB:
1474                         /* Call the library's callback */
1475                         user_ret = (op->u.lib_op)(loc, type, ndims, coords, op_data);
1476                     break;
1477                     default:
1478                         HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unsupported op type")
1479                 } /* end switch */
1480 
1481                 /* Increment offset in dataspace */
1482                 curr_off += elmt_size;
1483 
1484                 /* Decrement number of bytes left in sequence */
1485                 curr_len -= elmt_size;
1486             } /* end while */
1487         } /* end for */
1488 
1489         /* Decrement number of elements left to process */
1490         max_elem -= nelem;
1491     } /* end while */
1492 
1493     /* Set return value */
1494     ret_value = user_ret;
1495 
1496 done:
1497     /* Release resources, if allocated */
1498     if(len)
1499         len = H5FL_SEQ_FREE(size_t, len);
1500     if(off)
1501         off = H5FL_SEQ_FREE(hsize_t, off);
1502 
1503     /* Release selection iterator */
1504     if(iter_init && H5S_SELECT_ITER_RELEASE(iter) < 0)
1505         HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator")
1506     if(iter)
1507         iter = H5FL_FREE(H5S_sel_iter_t, iter);
1508 
1509     FUNC_LEAVE_NOAPI(ret_value)
1510 }   /* end H5S_select_iterate() */
1511 
1512 
1513 /*--------------------------------------------------------------------------
1514  NAME
1515     H5Sget_select_type
1516  PURPOSE
1517     Retrieve the type of selection in a dataspace
1518  USAGE
1519     H5S_sel_type H5Sget_select_type(space_id)
1520         hid_t space_id;	        IN: Dataspace object to query
1521  RETURNS
1522     Non-negative on success/Negative on failure.  Return value is from the
1523     set of values in the H5S_sel_type enumerated type.
1524  DESCRIPTION
1525 	This function retrieves the type of selection currently defined for
1526     a dataspace.
1527 --------------------------------------------------------------------------*/
1528 H5S_sel_type
H5Sget_select_type(hid_t space_id)1529 H5Sget_select_type(hid_t space_id)
1530 {
1531     H5S_t *space;	        /* dataspace to modify */
1532     H5S_sel_type ret_value;     /* Return value */
1533 
1534     FUNC_ENTER_API(H5S_SEL_ERROR)
1535     H5TRACE1("St", "i", space_id);
1536 
1537     /* Check args */
1538     if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
1539         HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, H5S_SEL_ERROR, "not a dataspace")
1540 
1541     /* Set return value */
1542     ret_value = H5S_GET_SELECT_TYPE(space);
1543 
1544 done:
1545     FUNC_LEAVE_API(ret_value)
1546 }   /* end H5Sget_select_type() */
1547 
1548 
1549 /*--------------------------------------------------------------------------
1550  NAME
1551     H5S_get_select_type
1552  PURPOSE
1553     Retrieve the type of selection in a dataspace
1554  USAGE
1555     H5S_sel_type H5Sget_select_type(space)
1556         const H5S_t *space;	        IN: Dataspace object to query
1557  RETURNS
1558     Non-negative on success/Negative on failure.  Return value is from the
1559     set of values in the H5S_sel_type enumerated type.
1560  DESCRIPTION
1561 	This function retrieves the type of selection currently defined for
1562     a dataspace.
1563  COMMENTS
1564      This routine participates in the "Inlining C function pointers"
1565         pattern, don't call it directly, use the appropriate macro
1566         defined in H5Sprivate.h.
1567 --------------------------------------------------------------------------*/
1568 H5S_sel_type
H5S_get_select_type(const H5S_t * space)1569 H5S_get_select_type(const H5S_t *space)
1570 {
1571     H5S_sel_type        ret_value = H5S_SEL_ERROR;      /* Return value */
1572 
1573     FUNC_ENTER_NOAPI_NOINIT_NOERR
1574 
1575     /* Check args */
1576     HDassert(space);
1577 
1578     /* Set return value */
1579     ret_value=H5S_GET_SELECT_TYPE(space);
1580 
1581     FUNC_LEAVE_NOAPI(ret_value)
1582 }   /* end H5S_get_select_type() */
1583 
1584 
1585 /*--------------------------------------------------------------------------
1586  NAME
1587     H5S_select_shape_same
1588  PURPOSE
1589     Check if two selections are the same shape
1590  USAGE
1591     htri_t H5S_select_shape_same(space1, space2)
1592         const H5S_t *space1;         IN: 1st Dataspace pointer to compare
1593         const H5S_t *space2;         IN: 2nd Dataspace pointer to compare
1594  RETURNS
1595     TRUE/FALSE/FAIL
1596  DESCRIPTION
1597     Checks to see if the current selection in the dataspaces are the same
1598     dimensionality and shape.
1599     This is primarily used for reading the entire selection in one swoop.
1600  GLOBAL VARIABLES
1601  COMMENTS, BUGS, ASSUMPTIONS
1602     Assumes that there is only a single "block" for hyperslab selections.
1603  EXAMPLES
1604  REVISION LOG
1605     Modified function to view identical shapes with different dimensions
1606     as being the same under some circumstances.
1607 --------------------------------------------------------------------------*/
1608 htri_t
H5S_select_shape_same(const H5S_t * space1,const H5S_t * space2)1609 H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2)
1610 {
1611     H5S_sel_iter_t *iter_a = NULL;  /* Selection a iteration info */
1612     H5S_sel_iter_t *iter_b = NULL;  /* Selection b iteration info */
1613     hbool_t iter_a_init = 0;  /* Selection a iteration info has been initialized */
1614     hbool_t iter_b_init = 0;  /* Selection b iteration info has been initialized */
1615     htri_t ret_value = TRUE; /* Return value */
1616 
1617     FUNC_ENTER_NOAPI(FAIL)
1618 
1619     /* Check args */
1620     HDassert(space1);
1621     HDassert(space2);
1622 
1623     /* Special case for one or both dataspaces being scalar */
1624     if(space1->extent.rank == 0 || space2->extent.rank == 0) {
1625         /* Check for different number of elements selected */
1626         if(H5S_GET_SELECT_NPOINTS(space1) != H5S_GET_SELECT_NPOINTS(space2))
1627             HGOTO_DONE(FALSE)
1628     } /* end if */
1629     else {
1630         const H5S_t *space_a;           /* Dataspace with larger rank */
1631         const H5S_t *space_b;           /* Dataspace with smaller rank */
1632         unsigned space_a_rank;          /* Number of dimensions of dataspace A */
1633         unsigned space_b_rank;          /* Number of dimensions of dataspace B */
1634 
1635         /* need to be able to handle spaces of different rank:
1636          *
1637          * To simplify logic, let space_a point to the element of the set
1638          * {space1, space2} with the largest rank or space1 if the ranks
1639          * are identical.
1640          *
1641          * Similarly, let space_b point to the element of {space1, space2}
1642          * with the smallest rank, or space2 if they are identical.
1643          *
1644          * Let:  space_a_rank be the rank of space_a,
1645          *       space_b_rank be the rank of space_b,
1646          *       delta_rank = space_a_rank - space_b_rank.
1647          *
1648          * Set all this up below.
1649          */
1650         if(space1->extent.rank >= space2->extent.rank) {
1651             space_a = space1;
1652             space_a_rank = space_a->extent.rank;
1653 
1654             space_b = space2;
1655             space_b_rank = space_b->extent.rank;
1656         } /* end if */
1657         else {
1658             space_a = space2;
1659             space_a_rank = space_a->extent.rank;
1660 
1661             space_b = space1;
1662             space_b_rank = space_b->extent.rank;
1663         } /* end else */
1664         HDassert(space_a_rank >= space_b_rank);
1665         HDassert(space_b_rank > 0);
1666 
1667         /* Check for different number of elements selected */
1668         if(H5S_GET_SELECT_NPOINTS(space_a) != H5S_GET_SELECT_NPOINTS(space_b))
1669             HGOTO_DONE(FALSE)
1670 
1671         /* Check for "easy" cases before getting into generalized block iteration code */
1672         if((H5S_GET_SELECT_TYPE(space_a) == H5S_SEL_ALL) && (H5S_GET_SELECT_TYPE(space_b) == H5S_SEL_ALL)) {
1673             hsize_t dims1[H5O_LAYOUT_NDIMS];    /* End point of selection block in dataspace #1 */
1674             hsize_t dims2[H5O_LAYOUT_NDIMS];    /* End point of selection block in dataspace #2 */
1675             int space_a_dim;                /* Current dimension in dataspace A */
1676             int space_b_dim;                /* Current dimension in dataspace B */
1677 
1678             if(H5S_get_simple_extent_dims(space_a, dims1, NULL) < 0)
1679                 HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality")
1680             if(H5S_get_simple_extent_dims(space_b, dims2, NULL) < 0)
1681                 HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality")
1682 
1683             space_a_dim = (int)space_a_rank - 1;
1684             space_b_dim = (int)space_b_rank - 1;
1685 
1686             /* recall that space_a_rank >= space_b_rank.
1687              *
1688              * In the following while loop, we test to see if space_a and space_b
1689              * have identical size in all dimensions they have in common.
1690              */
1691             while(space_b_dim >= 0) {
1692                 if(dims1[space_a_dim] != dims2[space_b_dim])
1693                     HGOTO_DONE(FALSE)
1694 
1695                 space_a_dim--;
1696                 space_b_dim--;
1697             } /* end while */
1698 
1699             /* Since we are selecting the entire spaces, we must also verify that space_a
1700              * has size 1 in all dimensions that it does not share with space_b.
1701              */
1702             while(space_a_dim >= 0) {
1703                 if(dims1[space_a_dim] != 1)
1704                     HGOTO_DONE(FALSE)
1705 
1706                 space_a_dim--;
1707             } /* end while */
1708         } /* end if */
1709         else if((H5S_GET_SELECT_TYPE(space1) == H5S_SEL_NONE) || (H5S_GET_SELECT_TYPE(space2) == H5S_SEL_NONE)) {
1710             HGOTO_DONE(TRUE)
1711         } /* end if */
1712         else if((H5S_GET_SELECT_TYPE(space_a) == H5S_SEL_HYPERSLABS && space_a->select.sel_info.hslab->diminfo_valid)
1713                 && (H5S_GET_SELECT_TYPE(space_b) == H5S_SEL_HYPERSLABS && space_b->select.sel_info.hslab->diminfo_valid)) {
1714             int space_a_dim;                /* Current dimension in dataspace A */
1715             int space_b_dim;                /* Current dimension in dataspace B */
1716 
1717             space_a_dim = (int)space_a_rank - 1;
1718             space_b_dim = (int)space_b_rank - 1;
1719 
1720             /* check that the shapes are the same in the common dimensions, and that
1721              * block == 1 in all dimensions that appear only in space_a.
1722              */
1723             while(space_b_dim >= 0) {
1724                 if(space_a->select.sel_info.hslab->opt_diminfo[space_a_dim].stride !=
1725                         space_b->select.sel_info.hslab->opt_diminfo[space_b_dim].stride)
1726                     HGOTO_DONE(FALSE)
1727 
1728                 if(space_a->select.sel_info.hslab->opt_diminfo[space_a_dim].count !=
1729                         space_b->select.sel_info.hslab->opt_diminfo[space_b_dim].count)
1730                     HGOTO_DONE(FALSE)
1731 
1732                 if(space_a->select.sel_info.hslab->opt_diminfo[space_a_dim].block !=
1733                         space_b->select.sel_info.hslab->opt_diminfo[space_b_dim].block)
1734                     HGOTO_DONE(FALSE)
1735 
1736                 space_a_dim--;
1737                 space_b_dim--;
1738             } /* end while */
1739 
1740             while(space_a_dim >= 0) {
1741                 if(space_a->select.sel_info.hslab->opt_diminfo[space_a_dim].block != 1)
1742                     HGOTO_DONE(FALSE)
1743 
1744                 space_a_dim--;
1745             } /* end while */
1746         } /* end if */
1747         /* Iterate through all the blocks in the selection */
1748         else {
1749             hsize_t start_a[H5O_LAYOUT_NDIMS]; /* Start point of selection block in dataspace a */
1750             hsize_t start_b[H5O_LAYOUT_NDIMS]; /* Start point of selection block in dataspace b */
1751             hsize_t end_a[H5O_LAYOUT_NDIMS];   /* End point of selection block in dataspace a */
1752             hsize_t end_b[H5O_LAYOUT_NDIMS];   /* End point of selection block in dataspace b */
1753             hsize_t off_a[H5O_LAYOUT_NDIMS];   /* Offset of selection a blocks */
1754             hsize_t off_b[H5O_LAYOUT_NDIMS];   /* Offset of selection b blocks */
1755             hbool_t first_block = TRUE;        /* Flag to indicate the first block */
1756 
1757             /* Allocate the selection iterators */
1758             if(NULL == (iter_a = H5FL_MALLOC(H5S_sel_iter_t)))
1759                 HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate selection iterator")
1760             if(NULL == (iter_b = H5FL_MALLOC(H5S_sel_iter_t)))
1761                 HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate selection iterator")
1762 
1763             /* Initialize iterator for each dataspace selection
1764              * Use '0' for element size instead of actual element size to indicate
1765              * that the selection iterator shouldn't be "flattened", since we
1766              * aren't actually going to be doing I/O with the iterators.
1767              */
1768             if(H5S_select_iter_init(iter_a, space_a, (size_t)0) < 0)
1769                 HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator a")
1770             iter_a_init = 1;
1771             if(H5S_select_iter_init(iter_b, space_b, (size_t)0) < 0)
1772                 HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator b")
1773             iter_b_init = 1;
1774 
1775             /* Iterate over all the blocks in each selection */
1776             while(1) {
1777                 int space_a_dim;                /* Current dimension in dataspace A */
1778                 int space_b_dim;                /* Current dimension in dataspace B */
1779                 htri_t status_a, status_b;      /* Status from next block checks */
1780 
1781                 /* Get the current block for each selection iterator */
1782                 if(H5S_SELECT_ITER_BLOCK(iter_a, start_a, end_a) < 0)
1783                     HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get iterator block a")
1784                 if(H5S_SELECT_ITER_BLOCK(iter_b, start_b, end_b) < 0)
1785                     HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get iterator block b")
1786 
1787                 space_a_dim = (int)space_a_rank - 1;
1788                 space_b_dim = (int)space_b_rank - 1;
1789 
1790                 /* The first block only compares the sizes and sets the
1791                  * relative offsets for later blocks
1792                  */
1793                 if(first_block) {
1794                     /* If the block sizes in the common dimensions from
1795                      * each selection don't match, get out
1796                      */
1797                     while(space_b_dim >= 0) {
1798                         if((end_a[space_a_dim] - start_a[space_a_dim]) !=
1799                                 (end_b[space_b_dim] - start_b[space_b_dim]))
1800                             HGOTO_DONE(FALSE)
1801 
1802                         /* Set the relative locations of the selections */
1803                         off_a[space_a_dim] = start_a[space_a_dim];
1804                         off_b[space_b_dim] = start_b[space_b_dim];
1805 
1806                         space_a_dim--;
1807                         space_b_dim--;
1808                     } /* end while */
1809 
1810                     /* similarly, if the block size in any dimension that appears only
1811                      * in space_a is not equal to 1, get out.
1812                      */
1813                     while(space_a_dim >= 0) {
1814                         if((end_a[space_a_dim] - start_a[space_a_dim]) != 0)
1815                             HGOTO_DONE(FALSE)
1816 
1817                         /* Set the relative locations of the selections */
1818                         off_a[space_a_dim] = start_a[space_a_dim];
1819 
1820                         space_a_dim--;
1821                     } /* end while */
1822 
1823                     /* Reset "first block" flag */
1824                     first_block = FALSE;
1825                 } /* end if */
1826                 /* Check over the blocks for each selection */
1827                 else {
1828                     /* for dimensions that space_a and space_b have in common: */
1829                     while(space_b_dim >= 0) {
1830                         /* Check if the blocks are in the same relative location */
1831                         if((start_a[space_a_dim] - off_a[space_a_dim]) !=
1832                                 (start_b[space_b_dim] - off_b[space_b_dim]))
1833                             HGOTO_DONE(FALSE)
1834 
1835                         /* If the block sizes from each selection doesn't match, get out */
1836                         if((end_a[space_a_dim] - start_a[space_a_dim]) !=
1837                                 (end_b[space_b_dim] - start_b[space_b_dim]))
1838                             HGOTO_DONE(FALSE)
1839 
1840                         space_a_dim--;
1841                         space_b_dim--;
1842                     } /* end while */
1843 
1844                     /* For dimensions that appear only in space_a: */
1845                     while(space_a_dim >= 0) {
1846                         /* If the block size isn't 1, get out */
1847                         if((end_a[space_a_dim] - start_a[space_a_dim]) != 0)
1848                             HGOTO_DONE(FALSE)
1849 
1850                         space_a_dim--;
1851                     } /* end while */
1852                 } /* end else */
1853 
1854                 /* Check if we are able to advance to the next selection block */
1855                 if((status_a = H5S_SELECT_ITER_HAS_NEXT_BLOCK(iter_a)) < 0)
1856                     HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to check iterator block a")
1857 
1858                 if((status_b = H5S_SELECT_ITER_HAS_NEXT_BLOCK(iter_b)) < 0)
1859                     HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to check iterator block b")
1860 
1861                 /* Did we run out of blocks at the same time? */
1862                 if((status_a == FALSE) && (status_b == FALSE))
1863                     break;
1864                 else if(status_a != status_b)
1865                     HGOTO_DONE(FALSE)
1866                 else {
1867                     /* Advance to next block in selection iterators */
1868                     if(H5S_SELECT_ITER_NEXT_BLOCK(iter_a) < 0)
1869                         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to advance to next iterator block a")
1870 
1871                     if(H5S_SELECT_ITER_NEXT_BLOCK(iter_b) < 0)
1872                         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to advance to next iterator block b")
1873                 } /* end else */
1874             } /* end while */
1875         } /* end else */
1876     } /* end else */
1877 
1878 done:
1879     if(iter_a_init && H5S_SELECT_ITER_RELEASE(iter_a) < 0)
1880         HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator a")
1881     if(iter_a)
1882         iter_a = H5FL_FREE(H5S_sel_iter_t, iter_a);
1883     if(iter_b_init && H5S_SELECT_ITER_RELEASE(iter_b) < 0)
1884         HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator b")
1885     if(iter_b)
1886         iter_b = H5FL_FREE(H5S_sel_iter_t, iter_b);
1887 
1888     FUNC_LEAVE_NOAPI(ret_value)
1889 }   /* H5S_select_shape_same() */
1890 
1891 
1892 /*--------------------------------------------------------------------------
1893  NAME
1894     H5S_select_construct_projection
1895 
1896  PURPOSE
1897     Given a dataspace a of rank n with some selection, construct a new
1898     dataspace b of rank m (m != n), with the selection in a being
1899     topologically identical to that in b (as verified by
1900     H5S_select_shape_same().
1901 
1902     This function exists, as some I/O code chokes of topologically
1903     identical selections with different ranks.  At least to begin
1904     with, we will deal with the issue by constructing projections
1905     of the memory dataspace with ranks equaling those of the file
1906     dataspace.
1907 
1908     Note that if m > n, it is possible that the starting point in the
1909     buffer associated with the memory dataspace will have to be
1910     adjusted to match the projected dataspace.  If the buf parameter
1911     is not NULL, the function must return an adjusted buffer base
1912     address in *adj_buf_ptr.
1913 
1914  USAGE
1915     htri_t H5S_select_construct_projection(base_space,
1916                                            new_space_ptr,
1917                                            new_space_rank,
1918                                            buf,
1919                                            adj_buf_ptr)
1920         const H5S_t *base_space;     IN: Ptr to Dataspace to project
1921         H5S_t ** new_space_ptr;     OUT: Ptr to location in which to return
1922 					 the address of the projected space
1923         int new_space_rank;	     IN: Rank of the projected space.
1924         const void * buf;            IN: Base address of the buffer
1925 					 associated with the base space.
1926 					 May be NULL.
1927         void ** adj_buf_ptr;        OUT: If buf != NULL, store the base
1928 					 address of the section of buf
1929 					 that is described by *new_space_ptr
1930 					 in *adj_buf_ptr.
1931 
1932  RETURNS
1933     Non-negative on success/Negative on failure.
1934 
1935  DESCRIPTION
1936     Construct a new dataspace and associated selection which is a
1937     projection of the supplied dataspace and associated selection into
1938     the specified rank.  Return it in *new_space_ptr.
1939 
1940     If buf is supplied, computes the base address of the projected
1941     selection in buf, and stores the base address in *adj_buf_ptr.
1942 
1943  GLOBAL VARIABLES
1944  COMMENTS, BUGS, ASSUMPTIONS
1945     The selection in the supplied base_space has thickness 1 in all
1946     dimensions greater than new_space_rank.  Note that here we count
1947     dimensions from the fastest changing coordinate to the slowest
1948     changing changing coordinate.
1949  EXAMPLES
1950  REVISION LOG
1951 --------------------------------------------------------------------------*/
1952 herr_t
H5S_select_construct_projection(const H5S_t * base_space,H5S_t ** new_space_ptr,unsigned new_space_rank,const void * buf,void const ** adj_buf_ptr,hsize_t element_size)1953 H5S_select_construct_projection(const H5S_t *base_space, H5S_t **new_space_ptr,
1954     unsigned new_space_rank, const void *buf, void const **adj_buf_ptr, hsize_t element_size)
1955 {
1956     H5S_t * new_space = NULL;           /* New dataspace constructed */
1957     hsize_t base_space_dims[H5S_MAX_RANK];      /* Current dimensions of base dataspace */
1958     hsize_t base_space_maxdims[H5S_MAX_RANK];   /* Maximum dimensions of base dataspace */
1959     int sbase_space_rank;               /* Signed # of dimensions of base dataspace */
1960     unsigned base_space_rank;           /* # of dimensions of base dataspace */
1961     hsize_t projected_space_element_offset = 0; /* Offset of selected element in projected buffer */
1962     herr_t ret_value = SUCCEED;         /* Return value */
1963 
1964     FUNC_ENTER_NOAPI(FAIL)
1965 
1966     /* Sanity checks */
1967     HDassert(base_space != NULL);
1968     HDassert((H5S_GET_EXTENT_TYPE(base_space) == H5S_SCALAR) || (H5S_GET_EXTENT_TYPE(base_space) == H5S_SIMPLE));
1969     HDassert(new_space_ptr != NULL);
1970     HDassert((new_space_rank != 0) || (H5S_GET_SELECT_NPOINTS(base_space) <= 1));
1971     HDassert(new_space_rank <= H5S_MAX_RANK);
1972     HDassert((buf == NULL) || (adj_buf_ptr != NULL));
1973     HDassert(element_size > 0 );
1974 
1975     /* Get the extent info for the base dataspace */
1976     if((sbase_space_rank = H5S_get_simple_extent_dims(base_space, base_space_dims, base_space_maxdims)) < 0)
1977         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality of base space")
1978     base_space_rank = (unsigned)sbase_space_rank;
1979     HDassert(base_space_rank != new_space_rank);
1980 
1981     /* Check if projected space is scalar */
1982     if(new_space_rank == 0) {
1983         hssize_t npoints;               /* Number of points selected */
1984 
1985         /* Retreve the number of elements selected */
1986         if((npoints = (hssize_t)H5S_GET_SELECT_NPOINTS(base_space)) < 0)
1987             HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get number of points selected")
1988         HDassert(npoints <= 1);
1989 
1990         /* Create new scalar dataspace */
1991         if(NULL == (new_space = H5S_create(H5S_SCALAR)))
1992             HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create scalar dataspace")
1993 
1994         /* No need to register the dataspace(i.e. get an ID) as
1995          * we will just be discarding it shortly.
1996          */
1997 
1998         /* Selection for the new space will be either all or
1999          * none, depending on whether the base space has 0 or
2000          * 1 elements selected.
2001          *
2002          * Observe that the base space can't have more than
2003          * one selected element, since its selection has the
2004          * same shape as the file dataspace, and that data
2005          * space is scalar.
2006          */
2007         if(1 == npoints) {
2008             /* Assuming that the selection in the base dataspace is not
2009              * empty, we must compute the offset of the selected item in
2010              * the buffer associated with the base dataspace.
2011              *
2012              * Since the new space rank is zero, we know that the
2013              * the base space must have rank at least 1 -- and
2014              * hence it is a simple dataspace.  However, the
2015              * selection, may be either point, hyperspace, or all.
2016              *
2017              */
2018             if(H5S_SELECT_PROJECT_SCALAR(base_space, &projected_space_element_offset) < 0)
2019                 HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "unable to project scalar selection")
2020         } /* end if */
2021         else {
2022             HDassert(0 == npoints);
2023 
2024             if(H5S_select_none(new_space) < 0)
2025                  HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't delete default selection")
2026         } /* end else */
2027     } /* end if */
2028     else { /* projected space must be simple */
2029         hsize_t new_space_dims[H5S_MAX_RANK];   /* Current dimensions for new dataspace */
2030         hsize_t new_space_maxdims[H5S_MAX_RANK];/* Maximum dimensions for new dataspace */
2031         unsigned rank_diff;             /* Difference in ranks */
2032 
2033         /* Set up the dimensions of the new, projected dataspace.
2034          *
2035          * How we do this depends on whether we are projecting up into
2036          * increased dimensions, or down into a reduced number of
2037          * dimensions.
2038          *
2039          * If we are projecting up (the first half of the following
2040          * if statement), we copy the dimensions of the base data
2041          * space into the fastest changing dimensions of the new
2042          * projected dataspace, and set the remaining dimensions to
2043          * one.
2044          *
2045          * If we are projecting down (the second half of the following
2046          * if statement), we just copy the dimensions with the most
2047          * quickly changing dimensions into the dims for the projected
2048          * data set.
2049          *
2050          * This works, because H5S_select_shape_same() will return
2051          * true on selections of different rank iff:
2052          *
2053          * 1) the selection in the lower rank dataspace matches that
2054          *    in the dimensions with the fastest changing indicies in
2055          *    the larger rank dataspace, and
2056          *
2057          * 2) the selection has thickness 1 in all ranks that appear
2058          *    only in the higher rank dataspace (i.e. those with
2059          *    more slowly changing indicies).
2060          */
2061         if(new_space_rank > base_space_rank) {
2062             hsize_t tmp_dim_size = 1;   /* Temporary dimension value, for filling arrays */
2063 
2064             /* we must copy the dimensions of the base space into
2065              * the fastest changing dimensions of the new space,
2066              * and set the remaining dimensions to 1
2067              */
2068             rank_diff = new_space_rank - base_space_rank;
2069             H5VM_array_fill(new_space_dims, &tmp_dim_size, sizeof(tmp_dim_size), rank_diff);
2070             H5VM_array_fill(new_space_maxdims, &tmp_dim_size, sizeof(tmp_dim_size), rank_diff);
2071             HDmemcpy(&new_space_dims[rank_diff], base_space_dims, sizeof(new_space_dims[0]) * base_space_rank);
2072             HDmemcpy(&new_space_maxdims[rank_diff], base_space_maxdims, sizeof(new_space_maxdims[0]) * base_space_rank);
2073         } /* end if */
2074         else { /* new_space_rank < base_space_rank */
2075             /* we must copy the fastest changing dimension of the
2076              * base space into the dimensions of the new space.
2077              */
2078             rank_diff = base_space_rank - new_space_rank;
2079             HDmemcpy(new_space_dims, &base_space_dims[rank_diff], sizeof(new_space_dims[0]) * new_space_rank);
2080             HDmemcpy(new_space_maxdims, &base_space_maxdims[rank_diff], sizeof(new_space_maxdims[0]) * new_space_rank);
2081         } /* end else */
2082 
2083         /* now have the new space rank and dimensions set up --
2084          * so we can create the new simple dataspace.
2085          */
2086         if(NULL == (new_space = H5S_create_simple(new_space_rank, new_space_dims, new_space_maxdims)))
2087             HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace")
2088 
2089         /* No need to register the dataspace(i.e. get an ID) as
2090          * we will just be discarding it shortly.
2091          */
2092 
2093         /* If we get this far, we have successfully created the projected
2094          * dataspace.  We must now project the selection in the base
2095          * dataspace into the projected dataspace.
2096          */
2097         if(H5S_SELECT_PROJECT_SIMPLE(base_space, new_space, &projected_space_element_offset) < 0)
2098             HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "unable to project simple selection")
2099 
2100         /* If we get this far, we have created the new dataspace, and projected
2101          * the selection in the base dataspace into the new dataspace.
2102          *
2103          * If the base dataspace is simple, check to see if the
2104          * offset_changed flag on the base selection has been set -- if so,
2105          * project the offset into the new dataspace and set the
2106          * offset_changed flag.
2107          */
2108         if(H5S_GET_EXTENT_TYPE(base_space) == H5S_SIMPLE && base_space->select.offset_changed) {
2109             if(new_space_rank > base_space_rank) {
2110                 HDmemset(new_space->select.offset, 0, sizeof(new_space->select.offset[0]) * rank_diff);
2111                 HDmemcpy(&new_space->select.offset[rank_diff], base_space->select.offset, sizeof(new_space->select.offset[0]) * base_space_rank);
2112             } /* end if */
2113             else
2114                 HDmemcpy(new_space->select.offset, &base_space->select.offset[rank_diff], sizeof(new_space->select.offset[0]) * new_space_rank);
2115 
2116             /* Propagate the offset changed flag into the new dataspace. */
2117             new_space->select.offset_changed = TRUE;
2118         } /* end if */
2119     } /* end else */
2120 
2121     /* If we have done the projection correctly, the following assertion
2122      * should hold.
2123      */
2124     HDassert(TRUE == H5S_select_shape_same(base_space, new_space));
2125 
2126     /* load the address of the new space into *new_space_ptr */
2127     *new_space_ptr = new_space;
2128 
2129     /* now adjust the buffer if required */
2130     if(buf != NULL) {
2131         if(new_space_rank < base_space_rank) {
2132             /* a bit of pointer magic here:
2133              *
2134              * Since we can't do pointer arithmetic on void pointers, we first
2135              * cast buf to a pointer to byte -- i.e. uint8_t.
2136              *
2137              * We then multiply the projected space element offset we
2138              * calculated earlier by the supplied element size, add this
2139              * value to the type cast buf pointer, cast the result back
2140              * to a pointer to void, and assign the result to *adj_buf_ptr.
2141              */
2142             *adj_buf_ptr = (const void *)(((const uint8_t *)buf) +
2143                     ((size_t)(projected_space_element_offset * element_size)));
2144         } /* end if */
2145         else
2146             /* No adjustment necessary */
2147             *adj_buf_ptr = buf;
2148     } /* end if */
2149 
2150 done:
2151     /* Cleanup on error */
2152     if(ret_value < 0) {
2153         if(new_space && H5S_close(new_space) < 0)
2154             HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace")
2155     } /* end if */
2156 
2157     FUNC_LEAVE_NOAPI(ret_value)
2158 }   /* H5S_select_construct_projection() */
2159 
2160 
2161 /*--------------------------------------------------------------------------
2162  NAME
2163     H5S_select_fill
2164  PURPOSE
2165     Fill a selection in memory with a value
2166  USAGE
2167     herr_t H5S_select_fill(fill,fill_size,space,buf)
2168         const void *fill;       IN: Pointer to fill value to use
2169         size_t fill_size;       IN: Size of elements in memory buffer & size of
2170                                     fill value
2171         H5S_t *space;           IN: Dataspace describing memory buffer &
2172                                     containing selection to use.
2173         void *buf;              IN/OUT: Memory buffer to fill selection in
2174  RETURNS
2175     Non-negative on success/Negative on failure.
2176  DESCRIPTION
2177     Use the selection in the dataspace to fill elements in a memory buffer.
2178  GLOBAL VARIABLES
2179  COMMENTS, BUGS, ASSUMPTIONS
2180     The memory buffer elements are assumed to have the same datatype as the
2181     fill value being placed into them.
2182  EXAMPLES
2183  REVISION LOG
2184 --------------------------------------------------------------------------*/
2185 herr_t
H5S_select_fill(const void * fill,size_t fill_size,const H5S_t * space,void * _buf)2186 H5S_select_fill(const void *fill, size_t fill_size, const H5S_t *space, void *_buf)
2187 {
2188     H5S_sel_iter_t *iter = NULL; /* Selection iteration info */
2189     hbool_t iter_init = 0;      /* Selection iteration info has been initialized */
2190     hsize_t *off = NULL;        /* Array to store sequence offsets */
2191     size_t *len = NULL;         /* Array to store sequence lengths */
2192     hssize_t nelmts;            /* Number of elements in selection */
2193     size_t max_elem;            /* Total number of elements in selection */
2194     herr_t ret_value = SUCCEED; /* Return value */
2195 
2196     FUNC_ENTER_NOAPI(FAIL)
2197 
2198     /* Check args */
2199     HDassert(fill);
2200     HDassert(fill_size > 0);
2201     HDassert(space);
2202     HDassert(_buf);
2203 
2204     /* Allocate the selection iterator */
2205     if(NULL == (iter = H5FL_MALLOC(H5S_sel_iter_t)))
2206         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate selection iterator")
2207 
2208     /* Initialize iterator */
2209     if(H5S_select_iter_init(iter, space, fill_size) < 0)
2210         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
2211     iter_init = 1;	/* Selection iteration info has been initialized */
2212 
2213     /* Get the number of elements in selection */
2214     if((nelmts = (hssize_t)H5S_GET_SELECT_NPOINTS(space)) < 0)
2215         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't get number of elements selected")
2216 
2217     /* Compute the number of bytes to process */
2218     H5_CHECKED_ASSIGN(max_elem, size_t, nelmts, hssize_t);
2219 
2220     /* Allocate the offset & length arrays */
2221     if(NULL == (len = H5FL_SEQ_MALLOC(size_t, H5D_IO_VECTOR_SIZE)))
2222         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate length vector array")
2223     if(NULL == (off = H5FL_SEQ_MALLOC(hsize_t, H5D_IO_VECTOR_SIZE)))
2224         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate offset vector array")
2225 
2226     /* Loop, while elements left in selection */
2227     while(max_elem > 0) {
2228         size_t nseq;                /* Number of sequences generated */
2229         size_t curr_seq;            /* Current sequnce being worked on */
2230         size_t nelem;               /* Number of elements used in sequences */
2231 
2232         /* Get the sequences of bytes */
2233         if(H5S_SELECT_GET_SEQ_LIST(space, 0, iter, (size_t)H5D_IO_VECTOR_SIZE, max_elem, &nseq, &nelem, off, len) < 0)
2234             HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed")
2235 
2236         /* Loop over sequences */
2237         for(curr_seq = 0; curr_seq < nseq; curr_seq++) {
2238             uint8_t *buf;               /* Current location in buffer */
2239 
2240             /* Get offset in memory buffer */
2241             buf = (uint8_t *)_buf + off[curr_seq];
2242 
2243             /* Fill each sequence in memory with fill value */
2244             HDassert((len[curr_seq] % fill_size) == 0);
2245             H5VM_array_fill(buf, fill, fill_size, (len[curr_seq] / fill_size));
2246         } /* end for */
2247 
2248         /* Decrement number of elements left to process */
2249         max_elem -= nelem;
2250     } /* end while */
2251 
2252 done:
2253     /* Release resources, if allocated */
2254     if(len)
2255         len = H5FL_SEQ_FREE(size_t, len);
2256     if(off)
2257         off = H5FL_SEQ_FREE(hsize_t, off);
2258 
2259     /* Release selection iterator */
2260     if(iter_init && H5S_SELECT_ITER_RELEASE(iter) < 0)
2261         HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator")
2262     if(iter)
2263         iter = H5FL_FREE(H5S_sel_iter_t, iter);
2264 
2265     FUNC_LEAVE_NOAPI(ret_value)
2266 }   /* H5S_select_fill() */
2267 
2268 
2269 /*--------------------------------------------------------------------------
2270  NAME
2271     H5S_select_project_intersection
2272 
2273  PURPOSE
2274     Projects the intersection of of the selections of src_space and
2275     src_intersect_space within the selection of src_space as a selection
2276     within the selection of dst_space
2277 
2278  USAGE
2279     herr_t H5S_select_project_intersection(src_space,dst_space,src_intersect_space,proj_space)
2280         H5S_t *src_space;       IN: Selection that is mapped to dst_space, and intersected with src_intersect_space
2281         H5S_t *dst_space;       IN: Selection that is mapped to src_space, and which contains the result
2282         H5S_t *src_intersect_space; IN: Selection whose intersection with src_space is projected to dst_space to obtain the result
2283         H5S_t *proj_space;      OUT: Will contain the result (intersection of src_intersect_space and src_space projected from src_space to dst_space) after the operation
2284 
2285  RETURNS
2286     Non-negative on success/Negative on failure.
2287 
2288  DESCRIPTION
2289     Projects the intersection of of the selections of src_space and
2290     src_intersect_space within the selection of src_space as a selection
2291     within the selection of dst_space.  The result is placed in the
2292     selection of proj_space.
2293 
2294  GLOBAL VARIABLES
2295  COMMENTS, BUGS, ASSUMPTIONS
2296  EXAMPLES
2297  REVISION LOG
2298 --------------------------------------------------------------------------*/
2299 herr_t
H5S_select_project_intersection(const H5S_t * src_space,const H5S_t * dst_space,const H5S_t * src_intersect_space,H5S_t ** new_space_ptr)2300 H5S_select_project_intersection(const H5S_t *src_space, const H5S_t *dst_space,
2301     const H5S_t *src_intersect_space, H5S_t **new_space_ptr)
2302 {
2303     H5S_t *new_space = NULL;           /* New dataspace constructed */
2304     herr_t ret_value = SUCCEED;         /* Return value */
2305 
2306     FUNC_ENTER_NOAPI(FAIL)
2307 
2308     /* Sanity checks */
2309     HDassert(src_space);
2310     HDassert(dst_space);
2311     HDassert(src_intersect_space);
2312     HDassert(new_space_ptr);
2313 
2314     /* Create new space, using dst extent.  Start with "all" selection. */
2315     if(NULL == (new_space = H5S_create(H5S_SIMPLE)))
2316         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create output dataspace")
2317     if(H5S_extent_copy_real(&new_space->extent, &dst_space->extent, TRUE) < 0)
2318         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy destination space extent")
2319 
2320     /* If the intersecting space is "all", the intersection must be equal to the
2321      * source space and the projection must be equal to the destination space */
2322     if(src_intersect_space->select.type->type == H5S_SEL_ALL) {
2323         /* Copy the destination selection. */
2324         if(H5S_select_copy(new_space, dst_space, FALSE) < 0)
2325             HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy destination space selection")
2326     } /* end if */
2327     /* If any of the spaces are "none", the projection must also be "none" */
2328     else if((src_intersect_space->select.type->type == H5S_SEL_NONE)
2329             || (src_space->select.type->type == H5S_SEL_NONE)
2330             || (dst_space->select.type->type == H5S_SEL_NONE)) {
2331         /* Change to "none" selection */
2332         if(H5S_select_none(new_space) < 0)
2333             HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
2334     } /* end if */
2335     /* If any of the spaces use point selection, fall back to general algorithm
2336      */
2337     else if((src_intersect_space->select.type->type == H5S_SEL_POINTS)
2338             || (src_space->select.type->type == H5S_SEL_POINTS)
2339             || (dst_space->select.type->type == H5S_SEL_POINTS))
2340         HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "point selections not currently supported")
2341     else {
2342         HDassert(src_intersect_space->select.type->type == H5S_SEL_HYPERSLABS);
2343         /* Intersecting space is hyperslab selection.  Call the hyperslab
2344          * routine to project to another hyperslab selection. */
2345         if(H5S__hyper_project_intersection(src_space, dst_space, src_intersect_space, new_space) < 0)
2346             HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't project hyperslab ondot destination selection")
2347     } /* end else */
2348 
2349     /* load the address of the new space into *new_space_ptr */
2350     *new_space_ptr = new_space;
2351 
2352 done:
2353     /* Cleanup on error */
2354     if(ret_value < 0) {
2355         if(new_space && H5S_close(new_space) < 0)
2356             HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace")
2357     } /* end if */
2358 
2359     FUNC_LEAVE_NOAPI(ret_value)
2360 } /* H5S_select_project_intersection() */
2361 
2362 
2363 /*--------------------------------------------------------------------------
2364  NAME
2365     H5S_select_subtract
2366 
2367  PURPOSE
2368     Subtract one selection from another
2369 
2370  USAGE
2371     herr_t H5S_select_subtract(space,subtract_space)
2372         H5S_t *space;           IN/OUT: Selection to be operated on
2373         H5S_t *subtract_space;  IN: Selection that will be subtracted from space
2374 
2375  RETURNS
2376     Non-negative on success/Negative on failure.
2377 
2378  DESCRIPTION
2379     Removes any and all portions of space that are also present in
2380     subtract_space.  In essence, performs an A_NOT_B operation with the
2381     two selections.
2382 
2383  GLOBAL VARIABLES
2384  COMMENTS, BUGS, ASSUMPTIONS
2385  EXAMPLES
2386  REVISION LOG
2387 --------------------------------------------------------------------------*/
2388 herr_t
H5S_select_subtract(H5S_t * space,H5S_t * subtract_space)2389 H5S_select_subtract(H5S_t *space, H5S_t *subtract_space)
2390 {
2391     herr_t ret_value = SUCCEED;         /* Return value */
2392 
2393     FUNC_ENTER_NOAPI(FAIL)
2394 
2395     /* Sanity checks */
2396     HDassert(space);
2397     HDassert(subtract_space);
2398 
2399     /* If either space is using the none selection, then we do not need to do
2400      * anything */
2401     if((space->select.type->type != H5S_SEL_NONE)
2402             && (subtract_space->select.type->type != H5S_SEL_NONE)) {
2403         /* If subtract_space is using the all selection, set space to none */
2404         if(subtract_space->select.type->type == H5S_SEL_ALL) {
2405             /* Change to "none" selection */
2406             if(H5S_select_none(space) < 0)
2407                 HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
2408         } /* end if */
2409         else {
2410             /* Check for point selection in subtract_space, convert to
2411              * hyperslab */
2412             if(subtract_space->select.type->type == H5S_SEL_POINTS)
2413                 HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "point selections not currently supported")
2414 
2415             /* Check for point or all selection in space, convert to hyperslab
2416              */
2417             if(space->select.type->type == H5S_SEL_ALL) {
2418                 /* Convert current "all" selection to "real" hyperslab selection */
2419                 /* Then allow operation to proceed */
2420                 hsize_t tmp_start[H5O_LAYOUT_NDIMS];    /* Temporary start information */
2421                 hsize_t tmp_stride[H5O_LAYOUT_NDIMS];   /* Temporary stride information */
2422                 hsize_t tmp_count[H5O_LAYOUT_NDIMS];    /* Temporary count information */
2423                 hsize_t tmp_block[H5O_LAYOUT_NDIMS];    /* Temporary block information */
2424                 unsigned i;                             /* Local index variable */
2425 
2426                 /* Fill in temporary information for the dimensions */
2427                 for(i = 0; i < space->extent.rank; i++) {
2428                     tmp_start[i] = 0;
2429                     tmp_stride[i] = 1;
2430                     tmp_count[i] = 1;
2431                     tmp_block[i] = space->extent.size[i];
2432                 } /* end for */
2433 
2434                 /* Convert to hyperslab selection */
2435                 if(H5S_select_hyperslab(space, H5S_SELECT_SET, tmp_start, tmp_stride, tmp_count, tmp_block) < 0)
2436                     HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection")
2437             } /* end if */
2438             else if(space->select.type->type == H5S_SEL_POINTS)
2439                 HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "point selections not currently supported")
2440 
2441             HDassert(space->select.type->type == H5S_SEL_HYPERSLABS);
2442             HDassert(subtract_space->select.type->type == H5S_SEL_HYPERSLABS);
2443 
2444             /* Both spaces are now hyperslabs, perform the operation */
2445             if(H5S__hyper_subtract(space, subtract_space) < 0)
2446                 HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't subtract hyperslab")
2447         } /* end else */
2448     } /* end if */
2449 
2450 done:
2451     FUNC_LEAVE_NOAPI(ret_value)
2452 } /* H5S_select_subtract() */
2453 
2454