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