Coverage Report

Created: 2026-10-28 18:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5Sselect.c
Line
Count
Source
1
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2
 * Copyright by The HDF Group.                                               *
3
 * All rights reserved.                                                      *
4
 *                                                                           *
5
 * This file is part of HDF5.  The full HDF5 copyright notice, including     *
6
 * terms governing use, modification, and redistribution, is contained in    *
7
 * the LICENSE file, which can be found at the root of the source code       *
8
 * distribution tree, or in https://www.hdfgroup.org/licenses.               *
9
 * If you do not have access to either file, you may request a copy from     *
10
 * help@hdfgroup.org.                                                        *
11
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13
/*
14
 * Purpose: Dataspace selection functions.
15
 */
16
17
/****************/
18
/* Module Setup */
19
/****************/
20
21
#include "H5Smodule.h" /* This source code file is part of the H5S module */
22
23
/***********/
24
/* Headers */
25
/***********/
26
#include "H5private.h"   /* Generic Functions     */
27
#include "H5Dprivate.h"  /* Datasets        */
28
#include "H5Eprivate.h"  /* Error handling        */
29
#include "H5FLprivate.h" /* Free Lists                           */
30
#include "H5Iprivate.h"  /* IDs           */
31
#include "H5MMprivate.h" /* Memory management                    */
32
#include "H5Spkg.h"      /* Dataspaces        */
33
#include "H5VMprivate.h" /* Vector and array functions    */
34
35
/****************/
36
/* Local Macros */
37
/****************/
38
39
/* All the valid public flags to H5Ssel_iter_create() */
40
0
#define H5S_SEL_ITER_ALL_PUBLIC_FLAGS (H5S_SEL_ITER_GET_SEQ_LIST_SORTED | H5S_SEL_ITER_SHARE_WITH_DATASPACE)
41
42
/******************/
43
/* Local Typedefs */
44
/******************/
45
46
/********************/
47
/* Local Prototypes */
48
/********************/
49
50
/*****************************/
51
/* Library Private Variables */
52
/*****************************/
53
54
/*********************/
55
/* Package Variables */
56
/*********************/
57
58
/* Declare a free list to manage the H5S_sel_iter_t struct */
59
H5FL_DEFINE(H5S_sel_iter_t);
60
61
/* Declare extern free list to manage sequences of size_t */
62
H5FL_SEQ_EXTERN(size_t);
63
64
/* Declare extern free list to manage sequences of hsize_t */
65
H5FL_SEQ_EXTERN(hsize_t);
66
67
/*******************/
68
/* Local Variables */
69
/*******************/
70
71
/*--------------------------------------------------------------------------
72
 NAME
73
    H5S_select_offset
74
 PURPOSE
75
    Set the selection offset for a datapace
76
 USAGE
77
    herr_t H5S_select_offset(space, offset)
78
        H5S_t *space;         IN/OUT: Dataspace object to set selection offset
79
        const hssize_t *offset; IN: Offset to position the selection at
80
 RETURNS
81
    Non-negative on success/Negative on failure
82
 DESCRIPTION
83
    Sets the selection offset for the dataspace
84
--------------------------------------------------------------------------*/
85
herr_t
86
H5S_select_offset(H5S_t *space, const hssize_t *offset)
87
0
{
88
0
    FUNC_ENTER_NOAPI_NOINIT_NOERR
89
90
    /* Check args */
91
0
    assert(space);
92
0
    assert(0 < space->extent.rank && space->extent.rank <= H5S_MAX_RANK);
93
94
    /* Copy the offset over. As a special case, when offset is NULL, we
95
     * reset all dimensions to zero.
96
     */
97
0
    if (offset)
98
0
        H5MM_memcpy(space->select.offset, offset, sizeof(hssize_t) * space->extent.rank);
99
0
    else
100
0
        memset(space->select.offset, 0, sizeof(hssize_t) * space->extent.rank);
101
102
    /* Indicate that the offset was changed */
103
0
    space->select.offset_changed = true;
104
105
0
    FUNC_LEAVE_NOAPI(SUCCEED)
106
0
} /* end H5S_select_offset() */
107
108
/*--------------------------------------------------------------------------
109
 NAME
110
    H5Soffset_simple
111
 PURPOSE
112
    Changes the offset of a selection within a simple dataspace extent
113
 USAGE
114
    herr_t H5Soffset_simple(space_id, offset)
115
        hid_t space_id;         IN: Dataspace object to reset
116
        const hssize_t *offset; IN: Offset to position the selection at
117
 RETURNS
118
    Non-negative on success/Negative on failure
119
 DESCRIPTION
120
        This function creates an offset for the selection within an extent, allowing
121
    the same shaped selection to be moved to different locations within a
122
    dataspace without requiring it to be re-defined.
123
--------------------------------------------------------------------------*/
124
herr_t
125
H5Soffset_simple(hid_t space_id, const hssize_t *offset)
126
0
{
127
0
    H5S_t *space;               /* Dataspace to modify */
128
0
    herr_t ret_value = SUCCEED; /* Return value */
129
130
0
    FUNC_ENTER_API(FAIL)
131
132
    /* Check args */
133
0
    if (NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
134
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADID, FAIL, "not a dataspace");
135
0
    if (space->extent.rank == 0 ||
136
0
        (H5S_GET_EXTENT_TYPE(space) == H5S_SCALAR || H5S_GET_EXTENT_TYPE(space) == H5S_NULL))
137
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "can't set offset on scalar or null dataspace");
138
139
    /* offset can be NULL (resets all dims to zero) */
140
141
    /* Set the selection offset */
142
0
    if (H5S_select_offset(space, offset) < 0)
143
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't set offset");
144
145
0
done:
146
0
    FUNC_LEAVE_API(ret_value)
147
0
} /* end H5Soffset_simple() */
148
149
/*--------------------------------------------------------------------------
150
 NAME
151
    H5Sselect_copy
152
 PURPOSE
153
    Copy a selection from one dataspace to another
154
 USAGE
155
    herr_t H5Sselect_copy(dst, src)
156
        hid_t   dst;              OUT: ID of the destination dataspace
157
        hid_t   src;              IN:  ID of the source dataspace
158
159
 RETURNS
160
    Non-negative on success/Negative on failure
161
 DESCRIPTION
162
    Copies all the selection information (including offset) from the source
163
    dataspace to the destination dataspace.
164
165
 GLOBAL VARIABLES
166
 COMMENTS, BUGS, ASSUMPTIONS
167
 EXAMPLES
168
 REVISION LOG
169
--------------------------------------------------------------------------*/
170
herr_t
171
H5Sselect_copy(hid_t dst_id, hid_t src_id)
172
0
{
173
0
    H5S_t *src;
174
0
    H5S_t *dst;
175
0
    herr_t ret_value = SUCCEED;
176
177
0
    FUNC_ENTER_API(FAIL)
178
179
    /* Check args */
180
0
    if (NULL == (src = (H5S_t *)H5I_object_verify(src_id, H5I_DATASPACE)))
181
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace");
182
0
    if (NULL == (dst = (H5S_t *)H5I_object_verify(dst_id, H5I_DATASPACE)))
183
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace");
184
185
    /* Copy */
186
0
    if (H5S_select_copy(dst, src, false) < 0)
187
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy selection");
188
189
0
done:
190
0
    FUNC_LEAVE_API(ret_value)
191
0
} /* end H5Sselect_copy() */
192
193
/*--------------------------------------------------------------------------
194
 NAME
195
    H5S_select_copy
196
 PURPOSE
197
    Copy a selection from one dataspace to another
198
 USAGE
199
    herr_t H5S_select_copy(dst, src, share_selection)
200
        H5S_t *dst;  OUT: Pointer to the destination dataspace
201
        H5S_t *src;  IN: Pointer to the source dataspace
202
        bool;     IN: Whether to share the selection between the dataspaces
203
 RETURNS
204
    Non-negative on success/Negative on failure
205
 DESCRIPTION
206
    Copies all the selection information (include offset) from the source
207
    dataspace to the destination dataspace.
208
209
    If the SHARE_SELECTION flag is set, then the selection can be shared
210
    between the source and destination dataspaces.  (This should only occur in
211
    situations where the destination dataspace will immediately change to a new
212
    selection)
213
 GLOBAL VARIABLES
214
 COMMENTS, BUGS, ASSUMPTIONS
215
 EXAMPLES
216
 REVISION LOG
217
--------------------------------------------------------------------------*/
218
herr_t
219
H5S_select_copy(H5S_t *dst, const H5S_t *src, bool share_selection)
220
237k
{
221
237k
    H5S_t  tmp_space;
222
237k
    bool   copied_space = false;
223
237k
    herr_t ret_value    = FAIL; /* Return value */
224
225
237k
    FUNC_ENTER_NOAPI(FAIL)
226
227
    /* Check args */
228
237k
    assert(dst);
229
237k
    assert(src);
230
231
237k
    tmp_space = *dst;
232
233
    /* Copy regular fields */
234
237k
    tmp_space.select = src->select;
235
236
    /* Perform correct type of copy based on the type of selection */
237
237k
    if ((ret_value = (*src->select.type->copy)(&tmp_space, src, share_selection)) < 0)
238
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy selection specific information");
239
237k
    copied_space = true;
240
241
    /* Release the current selection */
242
237k
    if (H5S_SELECT_RELEASE(dst) < 0)
243
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection");
244
245
237k
    *dst = tmp_space;
246
247
237k
done:
248
249
237k
    if (ret_value < 0) {
250
0
        if (copied_space && H5S_SELECT_RELEASE(&tmp_space) < 0)
251
0
            HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection");
252
0
    }
253
254
237k
    FUNC_LEAVE_NOAPI(ret_value)
255
237k
} /* end H5S_select_copy() */
256
257
/*-------------------------------------------------------------------------
258
 * Function:  H5S_select_release
259
 *
260
 * Purpose: Releases all memory associated with a dataspace selection.
261
 *
262
 * Return:  Non-negative on success/Negative on failure
263
 *
264
 * Note: This routine participates in the "Inlining C function pointers"
265
 *      pattern, don't call it directly, use the appropriate macro
266
 *      defined in H5Sprivate.h.
267
 *
268
 *-------------------------------------------------------------------------
269
 */
270
herr_t
271
H5S_select_release(H5S_t *ds)
272
707k
{
273
707k
    herr_t ret_value = SUCCEED; /* Return value */
274
275
707k
    FUNC_ENTER_NOAPI_NOINIT
276
277
707k
    assert(ds);
278
279
    /* Call the selection type's release function */
280
707k
    if ((ds->select.type) && ((ret_value = (*ds->select.type->release)(ds)) < 0))
281
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection");
282
283
707k
done:
284
707k
    FUNC_LEAVE_NOAPI(ret_value)
285
707k
} /* end H5S_select_release() */
286
287
/*-------------------------------------------------------------------------
288
 * Function:  H5S_select_serial_size
289
 *
290
 * Purpose: Determines the number of bytes required to store the current
291
 *              selection
292
 *
293
 * Return:  Non-negative on success/Negative on failure
294
 *
295
 * Note: This routine participates in the "Inlining C function pointers"
296
 *      pattern, don't call it directly, use the appropriate macro
297
 *      defined in H5Sprivate.h.
298
 *
299
 *-------------------------------------------------------------------------
300
 */
301
hssize_t
302
H5S_select_serial_size(H5S_t *space)
303
0
{
304
0
    hssize_t ret_value = -1; /* Return value */
305
306
0
    FUNC_ENTER_NOAPI_NOINIT_NOERR
307
308
0
    assert(space);
309
310
    /* Call the selection type's serial_size function */
311
0
    ret_value = (*space->select.type->serial_size)(space);
312
313
0
    FUNC_LEAVE_NOAPI(ret_value)
314
0
} /* end H5S_select_serial_size() */
315
316
/*--------------------------------------------------------------------------
317
 NAME
318
    H5S_select_serialize
319
 PURPOSE
320
    Serialize the selection for a dataspace into a buffer
321
 USAGE
322
    herr_t H5S_select_serialize(space, p)
323
        const H5S_t *space;     IN: Dataspace with selection to serialize
324
        uint8_t **p;            OUT: Pointer to buffer to put serialized
325
                                selection.  Will be advanced to end of
326
                                serialized selection.
327
 RETURNS
328
    Non-negative on success/Negative on failure
329
 DESCRIPTION
330
    Calls the appropriate dataspace selection callback to serialize the
331
    current selection into a buffer.
332
 GLOBAL VARIABLES
333
 COMMENTS, BUGS, ASSUMPTIONS
334
    This routine participates in the "Inlining C function pointers"
335
        pattern, don't call it directly, use the appropriate macro
336
        defined in H5Sprivate.h.
337
 EXAMPLES
338
 REVISION LOG
339
--------------------------------------------------------------------------*/
340
herr_t
341
H5S_select_serialize(H5S_t *space, uint8_t **p)
342
0
{
343
0
    herr_t ret_value = SUCCEED; /* Return value */
344
345
0
    FUNC_ENTER_NOAPI_NOINIT_NOERR
346
347
0
    assert(space);
348
0
    assert(p);
349
350
    /* Call the selection type's serialize function */
351
0
    ret_value = (*space->select.type->serialize)(space, p);
352
353
0
    FUNC_LEAVE_NOAPI(ret_value)
354
0
} /* end H5S_select_serialize() */
355
356
/*--------------------------------------------------------------------------
357
 NAME
358
    H5Sget_select_npoints
359
 PURPOSE
360
    Get the number of elements in current selection
361
 USAGE
362
    hssize_t H5Sget_select_npoints(dsid)
363
        hid_t dsid;             IN: Dataspace ID of selection to query
364
 RETURNS
365
    Non-negative on success/Negative on failure
366
 DESCRIPTION
367
    Returns the number of elements in current selection for dataspace.
368
 GLOBAL VARIABLES
369
 COMMENTS, BUGS, ASSUMPTIONS
370
 EXAMPLES
371
 REVISION LOG
372
--------------------------------------------------------------------------*/
373
hssize_t
374
H5Sget_select_npoints(hid_t spaceid)
375
0
{
376
0
    H5S_t   *space;     /* Dataspace to modify selection of */
377
0
    hssize_t ret_value; /* return value */
378
379
0
    FUNC_ENTER_API(FAIL)
380
381
    /* Check args */
382
0
    if (NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE)))
383
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace");
384
385
0
    ret_value = (hssize_t)H5S_GET_SELECT_NPOINTS(space);
386
387
0
done:
388
0
    FUNC_LEAVE_API(ret_value)
389
0
} /* H5Sget_select_npoints() */
390
391
/*--------------------------------------------------------------------------
392
 NAME
393
    H5S_get_select_npoints
394
 PURPOSE
395
    Get the number of elements in current selection
396
 USAGE
397
    hsize_t H5Sget_select_npoints(space)
398
        H5S_t *space;             IN: Dataspace of selection to query
399
 RETURNS
400
    The number of elements in selection on success, 0 on failure
401
 DESCRIPTION
402
    Returns the number of elements in current selection for dataspace.
403
 GLOBAL VARIABLES
404
 COMMENTS, BUGS, ASSUMPTIONS
405
     This routine participates in the "Inlining C function pointers"
406
        pattern, don't call it directly, use the appropriate macro
407
        defined in H5Sprivate.h.
408
 EXAMPLES
409
 REVISION LOG
410
--------------------------------------------------------------------------*/
411
H5_ATTR_PURE hsize_t
412
H5S_get_select_npoints(const H5S_t *space)
413
103k
{
414
103k
    FUNC_ENTER_NOAPI_NOINIT_NOERR
415
416
    /* Check args */
417
103k
    assert(space);
418
419
103k
    FUNC_LEAVE_NOAPI(space->select.num_elem)
420
103k
} /* end H5S_get_select_npoints() */
421
422
/*--------------------------------------------------------------------------
423
 NAME
424
    H5Sselect_valid
425
 PURPOSE
426
    Check whether the selection fits within the extent, with the current
427
    offset defined.
428
 USAGE
429
    htri_t H5Sselect_valid(dsid)
430
        hid_t dsid;             IN: Dataspace ID to query
431
 RETURNS
432
    true if the selection fits within the extent, false if it does not and
433
        Negative on an error.
434
 DESCRIPTION
435
    Determines if the current selection at the current offset fits within the
436
    extent for the dataspace.
437
 GLOBAL VARIABLES
438
 COMMENTS, BUGS, ASSUMPTIONS
439
 EXAMPLES
440
 REVISION LOG
441
--------------------------------------------------------------------------*/
442
htri_t
443
H5Sselect_valid(hid_t spaceid)
444
0
{
445
0
    H5S_t *space;     /* Dataspace to modify selection of */
446
0
    htri_t ret_value; /* return value */
447
448
0
    FUNC_ENTER_API(FAIL)
449
450
    /* Check args */
451
0
    if (NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE)))
452
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace");
453
454
0
    ret_value = H5S_SELECT_VALID(space);
455
456
0
done:
457
0
    FUNC_LEAVE_API(ret_value)
458
0
} /* end H5Sselect_valid() */
459
460
/*--------------------------------------------------------------------------
461
 NAME
462
    H5S_select_valid
463
 PURPOSE
464
    Check whether the selection fits within the extent, with the current
465
    offset defined.
466
 USAGE
467
    htri_t H5S_select_valid(space)
468
        H5S_t *space;           IN: Dataspace to query
469
 RETURNS
470
    true if the selection fits within the extent, false if it does not and
471
        Negative on an error.
472
 DESCRIPTION
473
    Determines if the current selection at the current offset fits within the
474
    extent for the dataspace.
475
 GLOBAL VARIABLES
476
 COMMENTS, BUGS, ASSUMPTIONS
477
     This routine participates in the "Inlining C function pointers"
478
        pattern, don't call it directly, use the appropriate macro
479
        defined in H5Sprivate.h.
480
 EXAMPLES
481
 REVISION LOG
482
--------------------------------------------------------------------------*/
483
htri_t
484
H5S_select_valid(const H5S_t *space)
485
103k
{
486
103k
    htri_t ret_value = FAIL; /* Return value */
487
488
103k
    FUNC_ENTER_NOAPI_NOINIT_NOERR
489
490
103k
    assert(space);
491
492
103k
    ret_value = (*space->select.type->is_valid)(space);
493
494
103k
    FUNC_LEAVE_NOAPI(ret_value)
495
103k
} /* end H5S_select_valid() */
496
497
/*--------------------------------------------------------------------------
498
 NAME
499
    H5S_select_deserialize
500
 PURPOSE
501
    Deserialize the current selection from a user-provided buffer into a real
502
        selection in the dataspace.
503
 USAGE
504
    herr_t H5S_select_deserialize(space, p)
505
        H5S_t **space;          IN/OUT: Dataspace pointer to place
506
                                selection into.  Will be allocated if not
507
                                provided.
508
        uint8 **p;              OUT: Pointer to buffer holding serialized
509
                                selection.  Will be advanced to end of
510
                                serialized selection.
511
 RETURNS
512
    Non-negative on success/Negative on failure
513
 DESCRIPTION
514
    Deserializes the current selection into a buffer.  (Primarily for retrieving
515
    from disk).  This routine just hands off to the appropriate routine for each
516
    type of selection.  The format of the serialized information is shown in
517
    the H5S_select_serialize() header.
518
 GLOBAL VARIABLES
519
 COMMENTS, BUGS, ASSUMPTIONS
520
 EXAMPLES
521
 REVISION LOG
522
--------------------------------------------------------------------------*/
523
herr_t
524
H5S_select_deserialize(H5S_t **space, const uint8_t **p, const size_t p_size)
525
0
{
526
0
    uint32_t       sel_type;         /* Pointer to the selection type */
527
0
    herr_t         ret_value = FAIL; /* Return value */
528
0
    const uint8_t *p_end     = NULL; /* Pointer to last valid byte in buffer */
529
0
    size_t         sel_info_size;    /* Size of selection-type-specific information */
530
0
    bool           skip = false;
531
532
0
    FUNC_ENTER_NOAPI(FAIL)
533
534
0
    assert(space);
535
536
    /* If p_size is unknown, skip buffer checks */
537
0
    skip = (p_size == SIZE_MAX ? true : false);
538
0
    if (skip)
539
0
        p_end = *p;
540
0
    else if (p_size < sizeof(uint32_t))
541
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_OVERFLOW, FAIL, "selection buffer too small");
542
0
    else
543
0
        p_end = *p + p_size - 1;
544
545
    /* Selection-type specific coding is moved to the callbacks. */
546
547
    /* Decode selection type */
548
0
    if (H5_IS_KNOWN_BUFFER_OVERFLOW(skip, *p, sizeof(uint32_t), p_end))
549
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_OVERFLOW, FAIL, "buffer overflow while decoding selection type");
550
0
    UINT32DECODE(*p, sel_type);
551
0
    sel_info_size = (skip ? SIZE_MAX : p_size - sizeof(uint32_t));
552
553
    /* Make routine for selection type */
554
0
    switch (sel_type) {
555
0
        case H5S_SEL_POINTS: /* Sequence of points selected */
556
0
            ret_value = (*H5S_sel_point->deserialize)(space, p, sel_info_size, skip);
557
0
            break;
558
559
0
        case H5S_SEL_HYPERSLABS: /* Hyperslab selection defined */
560
0
            ret_value = (*H5S_sel_hyper->deserialize)(space, p, sel_info_size, skip);
561
0
            break;
562
563
0
        case H5S_SEL_ALL: /* Entire extent selected */
564
0
            ret_value = (*H5S_sel_all->deserialize)(space, p, sel_info_size, skip);
565
0
            break;
566
567
0
        case H5S_SEL_NONE: /* Nothing selected */
568
0
            ret_value = (*H5S_sel_none->deserialize)(space, p, sel_info_size, skip);
569
0
            break;
570
571
0
        default:
572
0
            break;
573
0
    }
574
575
0
    if (ret_value < 0)
576
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTLOAD, FAIL, "can't deserialize selection");
577
578
0
done:
579
0
    FUNC_LEAVE_NOAPI(ret_value)
580
0
} /* end H5S_select_deserialize() */
581
582
/*--------------------------------------------------------------------------
583
 NAME
584
    H5Sget_select_bounds
585
 PURPOSE
586
    Gets the bounding box containing the selection.
587
 USAGE
588
    herr_t H5S_get_select_bounds(space, start, end)
589
        hid_t dsid;             IN: Dataspace ID of selection to query
590
        hsize_t start[];        OUT: Starting coordinate of bounding box
591
        hsize_t end[];          OUT: Opposite coordinate of bounding box
592
 RETURNS
593
    Non-negative on success, negative on failure
594
 DESCRIPTION
595
    Retrieves the bounding box containing the current selection and places
596
    it into the user's buffers.  The start and end buffers must be large
597
    enough to hold the dataspace rank number of coordinates.  The bounding box
598
    exactly contains the selection, ie. if a 2-D element selection is currently
599
    defined with the following points: (4,5), (6,8) (10,7), the bounding box
600
    with be (4, 5), (10, 8).  Calling this function on a "none" selection
601
    returns fail.
602
        The bounding box calculations _does_ include the current offset of the
603
    selection within the dataspace extent.
604
 GLOBAL VARIABLES
605
 COMMENTS, BUGS, ASSUMPTIONS
606
    This routine participates in the "Inlining C function pointers"
607
        pattern, don't call it directly, use the appropriate macro
608
        defined in H5Sprivate.h.
609
 EXAMPLES
610
 REVISION LOG
611
--------------------------------------------------------------------------*/
612
herr_t
613
H5Sget_select_bounds(hid_t spaceid, hsize_t start[] /*out*/, hsize_t end[] /*out*/)
614
0
{
615
0
    H5S_t *space;     /* Dataspace to modify selection of */
616
0
    herr_t ret_value; /* return value */
617
618
0
    FUNC_ENTER_API(FAIL)
619
620
    /* Check args */
621
0
    if (start == NULL || end == NULL)
622
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid pointer");
623
0
    if (NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE)))
624
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace");
625
626
0
    ret_value = H5S_SELECT_BOUNDS(space, start, end);
627
628
0
done:
629
0
    FUNC_LEAVE_API(ret_value)
630
0
} /* end H5Sget_select_bounds() */
631
632
/*--------------------------------------------------------------------------
633
 NAME
634
    H5S_get_select_bounds
635
 PURPOSE
636
    Gets the bounding box containing the selection.
637
 USAGE
638
    herr_t H5S_get_select_bounds(space, start, end)
639
        H5S_t *space;           IN: Dataspace ID of selection to query
640
        hsize_t *start;         OUT: Starting coordinate of bounding box
641
        hsize_t *end;           OUT: Opposite coordinate of bounding box
642
 RETURNS
643
    Non-negative on success, negative on failure
644
 DESCRIPTION
645
    Retrieves the bounding box containing the current selection and places
646
    it into the user's buffers.  The start and end buffers must be large
647
    enough to hold the dataspace rank number of coordinates.  The bounding box
648
    exactly contains the selection, ie. if a 2-D element selection is currently
649
    defined with the following points: (4,5), (6,8) (10,7), the bounding box
650
    with be (4, 5), (10, 8).  Calling this function on a "none" selection
651
    returns fail.
652
        The bounding box calculations _does_ include the current offset of the
653
    selection within the dataspace extent.
654
 GLOBAL VARIABLES
655
 COMMENTS, BUGS, ASSUMPTIONS
656
 EXAMPLES
657
 REVISION LOG
658
--------------------------------------------------------------------------*/
659
herr_t
660
H5S_get_select_bounds(const H5S_t *space, hsize_t *start, hsize_t *end)
661
0
{
662
0
    herr_t ret_value = FAIL; /* Return value */
663
664
0
    FUNC_ENTER_NOAPI_NOINIT_NOERR
665
666
    /* Check args */
667
0
    assert(space);
668
0
    assert(start);
669
0
    assert(end);
670
671
0
    ret_value = (*space->select.type->bounds)(space, start, end);
672
673
0
    FUNC_LEAVE_NOAPI(ret_value)
674
0
} /* end H5S_get_select_bounds() */
675
676
/*--------------------------------------------------------------------------
677
 NAME
678
    H5S_get_select_offset
679
 PURPOSE
680
    Gets the linear offset of the first element for the selection.
681
 USAGE
682
    herr_t H5S_get_select_offset(space, offset)
683
        const H5S_t *space;     IN: Dataspace pointer of selection to query
684
        hsize_t *offset;        OUT: Linear offset of first element in selection
685
 RETURNS
686
    Non-negative on success, negative on failure
687
 DESCRIPTION
688
    Retrieves the linear offset (in "units" of elements) of the first element
689
    selected within the dataspace.
690
 GLOBAL VARIABLES
691
 COMMENTS, BUGS, ASSUMPTIONS
692
        The offset calculation _does_ include the current offset of the
693
    selection within the dataspace extent.
694
695
        Calling this function on a "none" selection returns fail.
696
 EXAMPLES
697
 REVISION LOG
698
--------------------------------------------------------------------------*/
699
herr_t
700
H5S_get_select_offset(const H5S_t *space, hsize_t *offset)
701
706
{
702
706
    herr_t ret_value = FAIL; /* Return value */
703
704
706
    FUNC_ENTER_NOAPI_NOINIT_NOERR
705
706
    /* Check args */
707
706
    assert(space);
708
706
    assert(offset);
709
710
706
    ret_value = (*space->select.type->offset)(space, offset);
711
712
706
    FUNC_LEAVE_NOAPI(ret_value)
713
706
} /* end H5S_get_select_offset() */
714
715
/*--------------------------------------------------------------------------
716
 NAME
717
    H5S_get_select_unlim_dim
718
 PURPOSE
719
    Gets the unlimited dimension in the selection, or -1 if there is no
720
    unlimited dimension.
721
 USAGE
722
    int H5S_get_select_unlim_dim(space)
723
        const H5S_t *space;     IN: Dataspace pointer of selection to query
724
 RETURNS
725
    Unlimited dimension in the selection, or -1 if there is no unlimited
726
    dimension (never fails)
727
 DESCRIPTION
728
    Gets the unlimited dimension in the selection, or -1 if there is no
729
    unlimited dimension.
730
 GLOBAL VARIABLES
731
 COMMENTS, BUGS, ASSUMPTIONS
732
        Currently only implemented for hyperslab selections, all others
733
        simply return -1.
734
 EXAMPLES
735
 REVISION LOG
736
--------------------------------------------------------------------------*/
737
int
738
H5S_get_select_unlim_dim(const H5S_t *space)
739
0
{
740
0
    herr_t ret_value = FAIL; /* Return value */
741
742
0
    FUNC_ENTER_NOAPI_NOINIT_NOERR
743
744
    /* Check args */
745
0
    assert(space);
746
747
0
    ret_value = (*space->select.type->unlim_dim)(space);
748
749
0
    FUNC_LEAVE_NOAPI(ret_value)
750
0
} /* end H5S_get_select_unlim_dim() */
751
752
/*--------------------------------------------------------------------------
753
 NAME
754
    H5S_get_select_num_elem_non_unlim
755
 PURPOSE
756
    Gets the number of elements in the non-unlimited dimensions
757
 USAGE
758
    herr_t H5S_get_select_num_elem_non_unlim(space,num_elem_non_unlim)
759
        H5S_t *space;           IN: Dataspace pointer to check
760
        hsize_t *num_elem_non_unlim; OUT: Number of elements in the non-unlimited dimensions
761
 RETURNS
762
    Non-negative on success/Negative on failure
763
 DESCRIPTION
764
    Returns the number of elements in a slice through the non-unlimited
765
    dimensions of the selection.  Fails if the selection has no unlimited
766
    dimension.
767
 GLOBAL VARIABLES
768
 COMMENTS, BUGS, ASSUMPTIONS
769
 EXAMPLES
770
 REVISION LOG
771
--------------------------------------------------------------------------*/
772
herr_t
773
H5S_get_select_num_elem_non_unlim(const H5S_t *space, hsize_t *num_elem_non_unlim)
774
0
{
775
0
    herr_t ret_value = SUCCEED; /* return value */
776
777
0
    FUNC_ENTER_NOAPI(FAIL)
778
779
    /* Check args */
780
0
    assert(space);
781
0
    assert(num_elem_non_unlim);
782
783
    /* Check for selection callback */
784
0
    if (!space->select.type->num_elem_non_unlim)
785
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL,
786
0
                    "selection type has no num_elem_non_unlim callback");
787
788
    /* Make selection callback */
789
0
    if ((*space->select.type->num_elem_non_unlim)(space, num_elem_non_unlim) < 0)
790
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL,
791
0
                    "can't get number of elements in non-unlimited dimension");
792
793
0
done:
794
0
    FUNC_LEAVE_NOAPI(ret_value)
795
0
} /* end H5S_get_select_unlim_dim() */
796
797
/*--------------------------------------------------------------------------
798
 NAME
799
    H5S_select_is_contiguous
800
 PURPOSE
801
    Determines if a selection is contiguous in the dataspace
802
 USAGE
803
    htri_t H5S_select_is_contiguous(space)
804
        const H5S_t *space;             IN: Dataspace of selection to query
805
 RETURNS
806
    Non-negative (true/false) on success, negative on failure
807
 DESCRIPTION
808
    Checks the selection to determine if the points to iterated over will be
809
    contiguous in the particular dataspace.
810
 GLOBAL VARIABLES
811
 COMMENTS, BUGS, ASSUMPTIONS
812
    This routine participates in the "Inlining C function pointers"
813
        pattern, don't call it directly, use the appropriate macro
814
        defined in H5Sprivate.h.
815
 EXAMPLES
816
 REVISION LOG
817
--------------------------------------------------------------------------*/
818
htri_t
819
H5S_select_is_contiguous(const H5S_t *space)
820
0
{
821
0
    herr_t ret_value = FAIL; /* Return value */
822
823
0
    FUNC_ENTER_NOAPI_NOINIT_NOERR
824
825
    /* Check args */
826
0
    assert(space);
827
828
0
    ret_value = (*space->select.type->is_contiguous)(space);
829
830
0
    FUNC_LEAVE_NOAPI(ret_value)
831
0
} /* end H5S_select_is_contiguous() */
832
833
/*--------------------------------------------------------------------------
834
 NAME
835
    H5S_select_is_single
836
 PURPOSE
837
    Determines if a selection is a single block in the dataspace
838
 USAGE
839
    htri_t H5S_select_is_single(space)
840
        const H5S_t *space;             IN: Dataspace of selection to query
841
 RETURNS
842
    Non-negative (true/false) on success, negative on failure
843
 DESCRIPTION
844
    Checks the selection to determine if it occupies a single block in the
845
    particular dataspace.
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
htri_t
855
H5S_select_is_single(const H5S_t *space)
856
0
{
857
0
    herr_t ret_value = FAIL; /* Return value */
858
859
0
    FUNC_ENTER_NOAPI_NOINIT_NOERR
860
861
    /* Check args */
862
0
    assert(space);
863
864
0
    ret_value = (*space->select.type->is_single)(space);
865
866
0
    FUNC_LEAVE_NOAPI(ret_value)
867
0
} /* end H5S_select_is_single() */
868
869
/*--------------------------------------------------------------------------
870
 NAME
871
    H5S_select_is_regular
872
 PURPOSE
873
    Determines if a selection is "regular"  in the dataspace
874
 USAGE
875
    htri_t H5S_select_is_regular(space)
876
        const H5S_t *space;             IN: Dataspace of selection to query
877
 RETURNS
878
    Non-negative (true/false) on success, negative on failure
879
 DESCRIPTION
880
    Checks the selection to determine if it is "regular" (i.e. a single
881
    block or a strided pattern) in the particular dataspace.
882
 GLOBAL VARIABLES
883
 COMMENTS, BUGS, ASSUMPTIONS
884
    This routine participates in the "Inlining C function pointers"
885
        pattern, don't call it directly, use the appropriate macro
886
        defined in H5Sprivate.h.
887
 EXAMPLES
888
 REVISION LOG
889
--------------------------------------------------------------------------*/
890
htri_t
891
H5S_select_is_regular(H5S_t *space)
892
0
{
893
0
    herr_t ret_value = FAIL; /* Return value */
894
895
0
    FUNC_ENTER_NOAPI_NOINIT_NOERR
896
897
    /* Check args */
898
0
    assert(space);
899
900
0
    ret_value = (*space->select.type->is_regular)(space);
901
902
0
    FUNC_LEAVE_NOAPI(ret_value)
903
0
} /* end H5S_select_is_regular() */
904
905
/*--------------------------------------------------------------------------
906
 NAME
907
    H5S_select_adjust_u
908
 PURPOSE
909
    Adjust a selection by subtracting an offset
910
 USAGE
911
    herr_t H5S_select_adjust_u(space, offset)
912
        H5S_t *space;           IN/OUT: Pointer to dataspace to adjust
913
        const hsize_t *offset; IN: Offset to subtract
914
 RETURNS
915
    Non-negative on success, negative on failure
916
 DESCRIPTION
917
    Moves a selection by subtracting an offset from it.
918
 GLOBAL VARIABLES
919
 COMMENTS, BUGS, ASSUMPTIONS
920
    This routine participates in the "Inlining C function pointers"
921
        pattern, don't call it directly, use the appropriate macro
922
        defined in H5Sprivate.h.
923
 EXAMPLES
924
 REVISION LOG
925
--------------------------------------------------------------------------*/
926
herr_t
927
H5S_select_adjust_u(H5S_t *space, const hsize_t *offset)
928
0
{
929
0
    herr_t ret_value = SUCCEED; /* Return value */
930
931
0
    FUNC_ENTER_NOAPI_NOINIT_NOERR
932
933
    /* Check args */
934
0
    assert(space);
935
0
    assert(offset);
936
937
    /* Perform operation */
938
0
    ret_value = (*space->select.type->adjust_u)(space, offset);
939
940
0
    FUNC_LEAVE_NOAPI(ret_value)
941
0
} /* end H5S_select_adjust_u() */
942
943
/*--------------------------------------------------------------------------
944
 NAME
945
    H5S_select_adjust_s
946
 PURPOSE
947
    Adjust a selection by subtracting an offset
948
 USAGE
949
    herr_t H5S_select_adjust_s(space, offset)
950
        H5S_t *space;           IN/OUT: Pointer to dataspace to adjust
951
        const hssize_t *offset; IN: Offset to subtract
952
 RETURNS
953
    Non-negative on success, negative on failure
954
 DESCRIPTION
955
    Moves a selection by subtracting an offset from it.
956
 GLOBAL VARIABLES
957
 COMMENTS, BUGS, ASSUMPTIONS
958
    This routine participates in the "Inlining C function pointers"
959
        pattern, don't call it directly, use the appropriate macro
960
        defined in H5Sprivate.h.
961
 EXAMPLES
962
 REVISION LOG
963
--------------------------------------------------------------------------*/
964
herr_t
965
H5S_select_adjust_s(H5S_t *space, const hssize_t *offset)
966
0
{
967
0
    herr_t ret_value = SUCCEED; /* Return value */
968
969
0
    FUNC_ENTER_NOAPI_NOINIT_NOERR
970
971
    /* Check args */
972
0
    assert(space);
973
0
    assert(offset);
974
975
    /* Perform operation */
976
0
    ret_value = (*space->select.type->adjust_s)(space, offset);
977
978
0
    FUNC_LEAVE_NOAPI(ret_value)
979
0
} /* end H5S_select_adjust_s() */
980
981
/*--------------------------------------------------------------------------
982
 NAME
983
    H5Sselect_adjust
984
 PURPOSE
985
    Adjust a selection by subtracting an offset
986
 USAGE
987
    herr_t H5Sselect_adjust_u(space_id, offset)
988
        hid_t space_id;        IN: ID of dataspace to adjust
989
        const hsize_t *offset; IN: Offset to subtract
990
 RETURNS
991
    Non-negative on success, negative on failure
992
 DESCRIPTION
993
    Moves a selection by subtracting an offset from it.
994
 GLOBAL VARIABLES
995
 COMMENTS, BUGS, ASSUMPTIONS
996
 EXAMPLES
997
 REVISION LOG
998
--------------------------------------------------------------------------*/
999
herr_t
1000
H5Sselect_adjust(hid_t space_id, const hssize_t *offset)
1001
0
{
1002
0
    H5S_t   *space;
1003
0
    hsize_t  low_bounds[H5S_MAX_RANK];
1004
0
    hsize_t  high_bounds[H5S_MAX_RANK];
1005
0
    unsigned u;
1006
0
    herr_t   ret_value = SUCCEED; /* Return value */
1007
1008
0
    FUNC_ENTER_API(FAIL)
1009
1010
0
    if (NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
1011
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace");
1012
0
    if (NULL == offset)
1013
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "NULL offset pointer");
1014
1015
    /* Check bounds */
1016
0
    if (H5S_SELECT_BOUNDS(space, low_bounds, high_bounds) < 0)
1017
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get selection bounds");
1018
0
    for (u = 0; u < space->extent.rank; u++)
1019
0
        if (offset[u] > (hssize_t)low_bounds[u])
1020
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "adjustment would move selection below zero offset");
1021
1022
0
    if (H5S_select_adjust_s(space, offset) < 0)
1023
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't adjust selection");
1024
1025
0
done:
1026
0
    FUNC_LEAVE_API(ret_value)
1027
0
} /* end H5Sselect_adjust() */
1028
1029
/*--------------------------------------------------------------------------
1030
 NAME
1031
    H5S_select_project_scalar
1032
 PURPOSE
1033
    Project a single element selection for a scalar dataspace
1034
 USAGE
1035
    herr_t H5S_select_project_scalar(space, offset)
1036
        const H5S_t *space;             IN: Pointer to dataspace to project
1037
        hsize_t *offset;                IN/OUT: Offset of projected point
1038
 RETURNS
1039
    Non-negative on success, negative on failure
1040
 DESCRIPTION
1041
    Projects a selection of a single element into a scalar dataspace, computing
1042
    the offset of the element in the original selection.
1043
 GLOBAL VARIABLES
1044
 COMMENTS, BUGS, ASSUMPTIONS
1045
    This routine participates in the "Inlining C function pointers"
1046
        pattern, don't call it directly, use the appropriate macro
1047
        defined in H5Sprivate.h.
1048
 EXAMPLES
1049
 REVISION LOG
1050
--------------------------------------------------------------------------*/
1051
herr_t
1052
H5S_select_project_scalar(const H5S_t *space, hsize_t *offset)
1053
0
{
1054
0
    herr_t ret_value = FAIL; /* Return value */
1055
1056
0
    FUNC_ENTER_NOAPI_NOINIT_NOERR
1057
1058
    /* Check args */
1059
0
    assert(space);
1060
0
    assert(offset);
1061
1062
0
    ret_value = (*space->select.type->project_scalar)(space, offset);
1063
1064
0
    FUNC_LEAVE_NOAPI(ret_value)
1065
0
} /* end H5S_select_project_scalar() */
1066
1067
/*--------------------------------------------------------------------------
1068
 NAME
1069
    H5S_select_project_simple
1070
 PURPOSE
1071
    Project a selection onto/into a dataspace of different rank
1072
 USAGE
1073
    herr_t H5S_select_project_simple(space, new_space, offset)
1074
        const H5S_t *space;             IN: Pointer to dataspace to project
1075
        H5S_t *new_space;               IN/OUT: Pointer to dataspace projected onto
1076
        hsize_t *offset;                IN/OUT: Offset of projected point
1077
 RETURNS
1078
    Non-negative on success, negative on failure
1079
 DESCRIPTION
1080
    Projects a selection onto/into a simple dataspace, computing
1081
    the offset of the first element in the original selection.
1082
 GLOBAL VARIABLES
1083
 COMMENTS, BUGS, ASSUMPTIONS
1084
    This routine participates in the "Inlining C function pointers"
1085
        pattern, don't call it directly, use the appropriate macro
1086
        defined in H5Sprivate.h.
1087
 EXAMPLES
1088
 REVISION LOG
1089
--------------------------------------------------------------------------*/
1090
herr_t
1091
H5S_select_project_simple(const H5S_t *space, H5S_t *new_space, hsize_t *offset)
1092
0
{
1093
0
    herr_t ret_value = FAIL; /* Return value */
1094
1095
0
    FUNC_ENTER_NOAPI_NOINIT_NOERR
1096
1097
    /* Check args */
1098
0
    assert(space);
1099
0
    assert(new_space);
1100
0
    assert(offset);
1101
1102
0
    ret_value = (*space->select.type->project_simple)(space, new_space, offset);
1103
1104
0
    FUNC_LEAVE_NOAPI(ret_value)
1105
0
} /* end H5S_select_project_simple() */
1106
1107
/*--------------------------------------------------------------------------
1108
 NAME
1109
    H5S_select_iter_init
1110
 PURPOSE
1111
    Initializes iteration information for a selection.
1112
 USAGE
1113
    herr_t H5S_select_iter_init(sel_iter, space, elmt_size, flags)
1114
        H5S_sel_iter_t *sel_iter; OUT: Selection iterator to initialize.
1115
        H5S_t *space;           IN: Dataspace object containing selection to
1116
                                    iterate over
1117
        size_t elmt_size;       IN: Size of elements in the selection
1118
        unsigned flags;         IN: Flags to control iteration behavior
1119
 RETURNS
1120
     Non-negative on success, negative on failure.
1121
 DESCRIPTION
1122
    Initialize the selection iterator object to point to the first element
1123
    in the dataspace's selection.
1124
--------------------------------------------------------------------------*/
1125
herr_t
1126
H5S_select_iter_init(H5S_sel_iter_t *sel_iter, H5S_t *space, size_t elmt_size, unsigned flags)
1127
125k
{
1128
125k
    herr_t ret_value = FAIL; /* Return value */
1129
1130
125k
    FUNC_ENTER_NOAPI_NOINIT_NOERR
1131
1132
    /* Check args */
1133
125k
    assert(sel_iter);
1134
125k
    assert(space);
1135
1136
    /* Initialize common information */
1137
1138
    /* Save the dataspace's rank */
1139
125k
    sel_iter->rank = space->extent.rank;
1140
1141
    /* If dims > 0, copy the dataspace dimensions & selection offset */
1142
125k
    if (sel_iter->rank > 0) {
1143
125k
        H5MM_memcpy(sel_iter->dims, space->extent.size, sizeof(hsize_t) * space->extent.rank);
1144
125k
        H5MM_memcpy(sel_iter->sel_off, space->select.offset, sizeof(hsize_t) * space->extent.rank);
1145
125k
    }
1146
1147
    /* Save the element size */
1148
125k
    sel_iter->elmt_size = elmt_size;
1149
1150
    /* Initialize the number of elements to iterate over */
1151
125k
    sel_iter->elmt_left = space->select.num_elem;
1152
1153
    /* Set the flags for the iterator */
1154
125k
    sel_iter->flags = flags;
1155
1156
    /* Call initialization routine for selection type */
1157
125k
    ret_value = (*space->select.type->iter_init)(space, sel_iter);
1158
125k
    assert(sel_iter->type);
1159
1160
125k
    FUNC_LEAVE_NOAPI(ret_value)
1161
125k
} /* end H5S_select_iter_init() */
1162
1163
/*--------------------------------------------------------------------------
1164
 NAME
1165
    H5S_select_iter_coords
1166
 PURPOSE
1167
    Get the coordinates of the current iterator position
1168
 USAGE
1169
    herr_t H5S_select_iter_coords(sel_iter,coords)
1170
        H5S_sel_iter_t *sel_iter; IN: Selection iterator to query
1171
        hsize_t *coords;         OUT: Array to place iterator coordinates in
1172
 RETURNS
1173
    Non-negative on success, negative on failure.
1174
 DESCRIPTION
1175
    The current location of the iterator within the selection is placed in
1176
    the COORDS array.
1177
 GLOBAL VARIABLES
1178
 COMMENTS, BUGS, ASSUMPTIONS
1179
    This routine participates in the "Inlining C function pointers"
1180
        pattern, don't call it directly, use the appropriate macro
1181
        defined in H5Sprivate.h.
1182
 EXAMPLES
1183
 REVISION LOG
1184
--------------------------------------------------------------------------*/
1185
herr_t
1186
H5S_select_iter_coords(const H5S_sel_iter_t *sel_iter, hsize_t *coords)
1187
0
{
1188
0
    herr_t ret_value = FAIL; /* Return value */
1189
1190
0
    FUNC_ENTER_NOAPI_NOINIT_NOERR
1191
1192
    /* Check args */
1193
0
    assert(sel_iter);
1194
0
    assert(coords);
1195
1196
    /* Call iter_coords routine for selection type */
1197
0
    ret_value = (*sel_iter->type->iter_coords)(sel_iter, coords);
1198
1199
0
    FUNC_LEAVE_NOAPI(ret_value)
1200
0
} /* end H5S_select_iter_coords() */
1201
1202
/*--------------------------------------------------------------------------
1203
 NAME
1204
    H5S_select_iter_nelmts
1205
 PURPOSE
1206
    Get the number of elements left to iterate over in selection
1207
 USAGE
1208
    hssize_t H5S_select_iter_nelmts(sel_iter)
1209
        H5S_sel_iter_t *sel_iter; IN: Selection iterator to query
1210
 RETURNS
1211
    The number of elements in selection on success, 0 on failure
1212
 DESCRIPTION
1213
    Returns the number of elements in current selection for dataspace.
1214
 GLOBAL VARIABLES
1215
 COMMENTS, BUGS, ASSUMPTIONS
1216
    This routine participates in the "Inlining C function pointers"
1217
        pattern, don't call it directly, use the appropriate macro
1218
        defined in H5Sprivate.h.
1219
 EXAMPLES
1220
 REVISION LOG
1221
--------------------------------------------------------------------------*/
1222
hsize_t
1223
H5S_select_iter_nelmts(const H5S_sel_iter_t *sel_iter)
1224
0
{
1225
0
    hsize_t ret_value = 0; /* Return value */
1226
1227
0
    FUNC_ENTER_NOAPI_NOINIT_NOERR
1228
1229
    /* Check args */
1230
0
    assert(sel_iter);
1231
1232
    /* Call iter_nelmts routine for selection type */
1233
0
    ret_value = (*sel_iter->type->iter_nelmts)(sel_iter);
1234
1235
0
    FUNC_LEAVE_NOAPI(ret_value)
1236
0
} /* end H5S_select_iter_nelmts() */
1237
1238
/*--------------------------------------------------------------------------
1239
 NAME
1240
    H5S_select_iter_next
1241
 PURPOSE
1242
    Advance selection iterator to next element
1243
 USAGE
1244
    herr_t H5S_select_iter_next(iter, nelem)
1245
        H5S_sel_iter_t *iter;   IN/OUT: Selection iterator to change
1246
        size_t nelem;           IN: Number of elements to advance by
1247
 RETURNS
1248
    Non-negative on success, negative on failure.
1249
 DESCRIPTION
1250
    Move the current element for the selection iterator to the NELEM'th next
1251
    element in the selection.
1252
 GLOBAL VARIABLES
1253
 COMMENTS, BUGS, ASSUMPTIONS
1254
    This routine participates in the "Inlining C function pointers"
1255
        pattern, don't call it directly, use the appropriate macro
1256
        defined in H5Sprivate.h.
1257
 EXAMPLES
1258
 REVISION LOG
1259
--------------------------------------------------------------------------*/
1260
herr_t
1261
H5S_select_iter_next(H5S_sel_iter_t *iter, size_t nelem)
1262
0
{
1263
0
    herr_t ret_value = FAIL; /* Return value */
1264
1265
0
    FUNC_ENTER_NOAPI_NOINIT_NOERR
1266
1267
    /* Check args */
1268
0
    assert(iter);
1269
0
    assert(nelem > 0);
1270
1271
    /* Call iter_next routine for selection type */
1272
0
    ret_value = (*iter->type->iter_next)(iter, nelem);
1273
1274
    /* Decrement the number of elements left in selection */
1275
0
    iter->elmt_left -= nelem;
1276
1277
0
    FUNC_LEAVE_NOAPI(ret_value)
1278
0
} /* end H5S_select_iter_next() */
1279
1280
/*-------------------------------------------------------------------------
1281
 * Function:  H5S_select_iter_get_seq_list
1282
 *
1283
 * Purpose: Retrieves the next sequence of offset/length pairs for an
1284
 *              iterator on a dataspace
1285
 *
1286
 * Return:  Non-negative on success/Negative on failure
1287
 *
1288
 * Note: This routine participates in the "Inlining C function pointers"
1289
 *      pattern, don't call it directly, use the appropriate macro
1290
 *      defined in H5Sprivate.h.
1291
 *
1292
 *-------------------------------------------------------------------------
1293
 */
1294
herr_t
1295
H5S_select_iter_get_seq_list(H5S_sel_iter_t *iter, size_t maxseq, size_t maxelmts, size_t *nseq,
1296
                             size_t *nelmts, hsize_t *off, size_t *len)
1297
84.7k
{
1298
84.7k
    herr_t ret_value = FAIL; /* Return value */
1299
1300
84.7k
    FUNC_ENTER_NOAPI_NOINIT
1301
1302
    /* Sanity check */
1303
84.7k
    assert(iter);
1304
1305
    /* Call the selection type's get_seq_list function */
1306
84.7k
    if ((ret_value = (*iter->type->iter_get_seq_list)(iter, maxseq, maxelmts, nseq, nelmts, off, len)) < 0)
1307
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get selection sequence list");
1308
1309
84.7k
done:
1310
84.7k
    FUNC_LEAVE_NOAPI(ret_value)
1311
84.7k
} /* end H5S_select_iter_get_seq_list() */
1312
1313
/*--------------------------------------------------------------------------
1314
 NAME
1315
    H5S_select_iter_release
1316
 PURPOSE
1317
    Release a selection iterator's resources.
1318
 USAGE
1319
    herr_t H5S_select_iter_release(sel_iter)
1320
        H5S_sel_iter_t *sel_iter; IN: Selection iterator to query
1321
 RETURNS
1322
    The number of elements in selection on success, 0 on failure
1323
 DESCRIPTION
1324
    Returns the number of elements in current selection for dataspace.
1325
 GLOBAL VARIABLES
1326
 COMMENTS, BUGS, ASSUMPTIONS
1327
    This routine participates in the "Inlining C function pointers"
1328
        pattern, don't call it directly, use the appropriate macro
1329
        defined in H5Sprivate.h.
1330
 EXAMPLES
1331
 REVISION LOG
1332
--------------------------------------------------------------------------*/
1333
herr_t
1334
H5S_select_iter_release(H5S_sel_iter_t *sel_iter)
1335
116k
{
1336
116k
    herr_t ret_value = FAIL; /* Return value */
1337
1338
116k
    FUNC_ENTER_NOAPI_NOINIT_NOERR
1339
1340
    /* Check args */
1341
116k
    assert(sel_iter);
1342
1343
    /* Call selection type-specific release routine */
1344
116k
    ret_value = (*sel_iter->type->iter_release)(sel_iter);
1345
1346
116k
    FUNC_LEAVE_NOAPI(ret_value)
1347
116k
} /* end H5S_select_iter_release() */
1348
1349
/*--------------------------------------------------------------------------
1350
 NAME
1351
    H5S_select_iterate
1352
 PURPOSE
1353
    Iterate over the selected elements in a memory buffer.
1354
 USAGE
1355
    herr_t H5S_select_iterate(buf, type, space, operator, operator_data)
1356
        void *buf;      IN/OUT: Buffer containing elements to iterate over
1357
        H5T_t *type;    IN: Datatype of BUF array.
1358
        H5S_t *space;   IN: Dataspace object containing selection to iterate over
1359
        H5D_operator_t op; IN: Function pointer to the routine to be
1360
                                called for each element in BUF iterated over.
1361
        void *operator_data;    IN/OUT: Pointer to any user-defined data
1362
                                associated with the operation.
1363
 RETURNS
1364
    Returns the return value of the last operator if it was non-zero, or zero
1365
    if all elements were processed. Otherwise returns a negative value.
1366
 DESCRIPTION
1367
    Iterates over the selected elements in a memory buffer, calling the user's
1368
    callback function for each element.  The selection in the dataspace is
1369
    modified so that any elements already iterated over are removed from the
1370
    selection if the iteration is interrupted (by the H5D_operator_t function
1371
    returning non-zero) in the "middle" of the iteration and may be re-started
1372
    by the user where it left off.
1373
1374
    NOTE: Until "subtracting" elements from a selection is implemented,
1375
        the selection is not modified.
1376
--------------------------------------------------------------------------*/
1377
herr_t
1378
H5S_select_iterate(void *buf, const H5T_t *type, H5S_t *space, const H5S_sel_iter_op_t *op, void *op_data)
1379
7.72k
{
1380
7.72k
    H5S_sel_iter_t *iter      = NULL;         /* Selection iteration info */
1381
7.72k
    bool            iter_init = false;        /* Selection iteration info has been initialized */
1382
7.72k
    hsize_t        *off       = NULL;         /* Array to store sequence offsets */
1383
7.72k
    size_t         *len       = NULL;         /* Array to store sequence lengths */
1384
7.72k
    hssize_t        nelmts;                   /* Number of elements in selection */
1385
7.72k
    hsize_t         space_size[H5S_MAX_RANK]; /* Dataspace size */
1386
7.72k
    size_t          max_elem;                 /* Maximum number of elements allowed in sequences */
1387
7.72k
    size_t          elmt_size;                /* Datatype size */
1388
7.72k
    unsigned        ndims;                    /* Number of dimensions in dataspace */
1389
7.72k
    herr_t          user_ret  = 0;            /* User's return value */
1390
7.72k
    herr_t          ret_value = SUCCEED;      /* Return value */
1391
1392
7.72k
    FUNC_ENTER_NOAPI(FAIL)
1393
1394
    /* Check args */
1395
7.72k
    assert(buf);
1396
7.72k
    assert(type);
1397
7.72k
    assert(space);
1398
7.72k
    assert(op);
1399
1400
    /* Get the datatype size */
1401
7.72k
    if (0 == (elmt_size = H5T_get_size(type)))
1402
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_BADSIZE, FAIL, "datatype size invalid");
1403
1404
    /* Allocate the selection iterator */
1405
7.72k
    if (NULL == (iter = H5FL_MALLOC(H5S_sel_iter_t)))
1406
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate selection iterator");
1407
1408
    /* Initialize iterator */
1409
7.72k
    if (H5S_select_iter_init(iter, space, elmt_size, 0) < 0)
1410
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator");
1411
7.72k
    iter_init = true; /* Selection iteration info has been initialized */
1412
1413
    /* Get the number of elements in selection */
1414
7.72k
    if ((nelmts = (hssize_t)H5S_GET_SELECT_NPOINTS(space)) < 0)
1415
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't get number of elements selected");
1416
1417
    /* Get the rank of the dataspace */
1418
7.72k
    ndims = space->extent.rank;
1419
1420
7.72k
    if (ndims > 0) {
1421
        /* Copy the size of the space */
1422
7.72k
        assert(space->extent.size);
1423
7.72k
        H5MM_memcpy(space_size, space->extent.size, ndims * sizeof(hsize_t));
1424
7.72k
    } /* end if */
1425
7.72k
    space_size[ndims] = elmt_size;
1426
1427
    /* Compute the maximum number of bytes required */
1428
7.72k
    H5_CHECKED_ASSIGN(max_elem, size_t, nelmts, hssize_t);
1429
1430
    /* Allocate the offset & length arrays */
1431
7.72k
    if (NULL == (len = H5FL_SEQ_MALLOC(size_t, H5D_IO_VECTOR_SIZE)))
1432
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate length vector array");
1433
7.72k
    if (NULL == (off = H5FL_SEQ_MALLOC(hsize_t, H5D_IO_VECTOR_SIZE)))
1434
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate offset vector array");
1435
1436
    /* Loop, while elements left in selection */
1437
15.4k
    while (max_elem > 0 && user_ret == 0) {
1438
7.72k
        size_t nelem;    /* Number of elements used in sequences */
1439
7.72k
        size_t nseq;     /* Number of sequences generated */
1440
7.72k
        size_t curr_seq; /* Current sequence being worked on */
1441
1442
        /* Get the sequences of bytes */
1443
7.72k
        if (H5S_SELECT_ITER_GET_SEQ_LIST(iter, (size_t)H5D_IO_VECTOR_SIZE, max_elem, &nseq, &nelem, off,
1444
7.72k
                                         len) < 0)
1445
0
            HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed");
1446
1447
        /* Loop, while sequences left to process */
1448
15.4k
        for (curr_seq = 0; curr_seq < nseq && user_ret == 0; curr_seq++) {
1449
7.72k
            hsize_t curr_off; /* Current offset within sequence */
1450
7.72k
            size_t  curr_len; /* Length of bytes left to process in sequence */
1451
1452
            /* Get the current offset */
1453
7.72k
            curr_off = off[curr_seq];
1454
1455
            /* Get the number of bytes in sequence */
1456
7.72k
            curr_len = len[curr_seq];
1457
1458
            /* Loop, while bytes left in sequence */
1459
46.6k
            while (curr_len > 0 && user_ret == 0) {
1460
38.9k
                hsize_t  coords[H5S_MAX_RANK]; /* Coordinates of element in dataspace */
1461
38.9k
                hsize_t  tmp_off;              /* Temporary offset within sequence */
1462
38.9k
                uint8_t *loc;                  /* Current element location in buffer */
1463
38.9k
                int      i;                    /* Local Index variable */
1464
1465
                /* Compute the coordinate from the offset */
1466
116k
                for (i = (int)ndims, tmp_off = curr_off; i >= 0; i--) {
1467
77.9k
                    coords[i] = tmp_off % space_size[i];
1468
77.9k
                    tmp_off /= space_size[i];
1469
77.9k
                } /* end for */
1470
1471
                /* Get the location within the user's buffer */
1472
38.9k
                loc = (unsigned char *)buf + curr_off;
1473
1474
                /* Check which type of callback to make */
1475
38.9k
                switch (op->op_type) {
1476
0
                    case H5S_SEL_ITER_OP_APP:
1477
                        /* Prepare & restore library for user callback */
1478
0
                        H5_BEFORE_USER_CB(H5_ITER_ERROR)
1479
0
                            {
1480
                                /* Make the application callback */
1481
0
                                user_ret =
1482
0
                                    (op->u.app_op.op)(loc, op->u.app_op.type_id, ndims, coords, op_data);
1483
0
                            }
1484
0
                        H5_AFTER_USER_CB(H5_ITER_ERROR)
1485
0
                        break;
1486
1487
38.9k
                    case H5S_SEL_ITER_OP_LIB:
1488
                        /* Call the library's callback */
1489
38.9k
                        user_ret = (op->u.lib_op)(loc, type, ndims, coords, op_data);
1490
38.9k
                        break;
1491
1492
0
                    default:
1493
0
                        HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unsupported op type");
1494
38.9k
                } /* end switch */
1495
1496
                /* Check for error return from iterator */
1497
38.9k
                if (user_ret < 0)
1498
0
                    HERROR(H5E_DATASPACE, H5E_CANTNEXT, "iteration operator failed");
1499
1500
                /* Increment offset in dataspace */
1501
38.9k
                curr_off += elmt_size;
1502
1503
                /* Decrement number of bytes left in sequence */
1504
38.9k
                curr_len -= elmt_size;
1505
38.9k
            } /* end while */
1506
7.72k
        }     /* end for */
1507
1508
        /* Decrement number of elements left to process */
1509
7.72k
        max_elem -= nelem;
1510
7.72k
    } /* end while */
1511
1512
    /* Set return value */
1513
7.72k
    ret_value = user_ret;
1514
1515
7.72k
done:
1516
    /* Release resources, if allocated */
1517
7.72k
    if (len)
1518
7.72k
        len = H5FL_SEQ_FREE(size_t, len);
1519
7.72k
    if (off)
1520
7.72k
        off = H5FL_SEQ_FREE(hsize_t, off);
1521
1522
    /* Release selection iterator */
1523
7.72k
    if (iter_init && H5S_SELECT_ITER_RELEASE(iter) < 0)
1524
0
        HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator");
1525
7.72k
    if (iter)
1526
7.72k
        iter = H5FL_FREE(H5S_sel_iter_t, iter);
1527
1528
7.72k
    FUNC_LEAVE_NOAPI(ret_value)
1529
7.72k
} /* end H5S_select_iterate() */
1530
1531
/*--------------------------------------------------------------------------
1532
 NAME
1533
    H5Sget_select_type
1534
 PURPOSE
1535
    Retrieve the type of selection in a dataspace
1536
 USAGE
1537
    H5S_sel_type H5Sget_select_type(space_id)
1538
        hid_t space_id;         IN: Dataspace object to query
1539
 RETURNS
1540
    Non-negative on success/Negative on failure.  Return value is from the
1541
    set of values in the H5S_sel_type enumerated type.
1542
 DESCRIPTION
1543
        This function retrieves the type of selection currently defined for
1544
    a dataspace.
1545
--------------------------------------------------------------------------*/
1546
H5S_sel_type
1547
H5Sget_select_type(hid_t space_id)
1548
0
{
1549
0
    H5S_t       *space;     /* dataspace to modify */
1550
0
    H5S_sel_type ret_value; /* Return value */
1551
1552
0
    FUNC_ENTER_API(H5S_SEL_ERROR)
1553
1554
    /* Check args */
1555
0
    if (NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
1556
0
        HGOTO_ERROR(H5E_ID, H5E_BADID, H5S_SEL_ERROR, "not a dataspace");
1557
1558
    /* Set return value */
1559
0
    ret_value = H5S_GET_SELECT_TYPE(space);
1560
1561
0
done:
1562
0
    FUNC_LEAVE_API(ret_value)
1563
0
} /* end H5Sget_select_type() */
1564
1565
/*--------------------------------------------------------------------------
1566
 NAME
1567
    H5S_get_select_type
1568
 PURPOSE
1569
    Retrieve the type of selection in a dataspace
1570
 USAGE
1571
    H5S_sel_type H5Sget_select_type(space)
1572
        const H5S_t *space;         IN: Dataspace object to query
1573
 RETURNS
1574
    Non-negative on success/Negative on failure.  Return value is from the
1575
    set of values in the H5S_sel_type enumerated type.
1576
 DESCRIPTION
1577
        This function retrieves the type of selection currently defined for
1578
    a dataspace.
1579
 COMMENTS
1580
     This routine participates in the "Inlining C function pointers"
1581
        pattern, don't call it directly, use the appropriate macro
1582
        defined in H5Sprivate.h.
1583
--------------------------------------------------------------------------*/
1584
H5_ATTR_PURE H5S_sel_type
1585
H5S_get_select_type(const H5S_t *space)
1586
0
{
1587
0
    H5S_sel_type ret_value = H5S_SEL_ERROR; /* Return value */
1588
1589
0
    FUNC_ENTER_NOAPI_NOINIT_NOERR
1590
1591
    /* Check args */
1592
0
    assert(space);
1593
1594
    /* Set return value */
1595
0
    ret_value = H5S_GET_SELECT_TYPE(space);
1596
1597
0
    FUNC_LEAVE_NOAPI(ret_value)
1598
0
} /* end H5S_get_select_type() */
1599
1600
/*--------------------------------------------------------------------------
1601
 NAME
1602
    H5S_select_shape_same
1603
 PURPOSE
1604
    Check if two selections are the same shape
1605
 USAGE
1606
    htri_t H5S_select_shape_same(space1, space2)
1607
        const H5S_t *space1;         IN: 1st Dataspace pointer to compare
1608
        const H5S_t *space2;         IN: 2nd Dataspace pointer to compare
1609
 RETURNS
1610
    true/false/FAIL
1611
 DESCRIPTION
1612
    Checks to see if the current selection in the dataspaces are the same
1613
    dimensionality and shape.
1614
1615
    This is primarily used for reading the entire selection in one swoop.
1616
 GLOBAL VARIABLES
1617
 COMMENTS, BUGS, ASSUMPTIONS
1618
    This routine participates in the "Inlining C function pointers" pattern,
1619
    don't call it directly, use the appropriate macro defined in H5Sprivate.h.
1620
 EXAMPLES
1621
 REVISION LOG
1622
--------------------------------------------------------------------------*/
1623
htri_t
1624
H5S_select_shape_same(H5S_t *space1, H5S_t *space2)
1625
43.0k
{
1626
43.0k
    H5S_sel_iter_t *iter_a      = NULL;  /* Selection a iteration info */
1627
43.0k
    H5S_sel_iter_t *iter_b      = NULL;  /* Selection b iteration info */
1628
43.0k
    bool            iter_a_init = false; /* Selection a iteration info has been initialized */
1629
43.0k
    bool            iter_b_init = false; /* Selection b iteration info has been initialized */
1630
43.0k
    htri_t          ret_value   = true;  /* Return value */
1631
1632
43.0k
    FUNC_ENTER_NOAPI(FAIL)
1633
1634
    /* Check args */
1635
43.0k
    assert(space1);
1636
43.0k
    assert(space2);
1637
1638
    /* Check for different number of elements selected */
1639
43.0k
    if (H5S_GET_SELECT_NPOINTS(space1) != H5S_GET_SELECT_NPOINTS(space2))
1640
0
        HGOTO_DONE(false);
1641
1642
    /* Check special cases if both dataspaces aren't scalar */
1643
    /* (If only one is, the number of selected points check is sufficient) */
1644
43.0k
    if (space1->extent.rank > 0 && space2->extent.rank > 0) {
1645
43.0k
        H5S_t       *space_a;      /* Dataspace with larger rank */
1646
43.0k
        H5S_t       *space_b;      /* Dataspace with smaller rank */
1647
43.0k
        unsigned     space_a_rank; /* Number of dimensions of dataspace A */
1648
43.0k
        unsigned     space_b_rank; /* Number of dimensions of dataspace B */
1649
43.0k
        int          space_a_dim;  /* Current dimension in dataspace A */
1650
43.0k
        int          space_b_dim;  /* Current dimension in dataspace B */
1651
43.0k
        H5S_sel_type sel_a_type;   /* Selection type for dataspace A */
1652
43.0k
        H5S_sel_type sel_b_type;   /* Selection type for dataspace B */
1653
1654
        /* Need to be able to handle spaces of different rank:
1655
         *
1656
         * To simplify logic, let space_a point to the element of the set
1657
         * {space1, space2} with the largest rank or space1 if the ranks
1658
         * are identical.
1659
         *
1660
         * Similarly, let space_b point to the element of {space1, space2}
1661
         * with the smallest rank, or space2 if they are identical.
1662
         *
1663
         * Let:  space_a_rank be the rank of space_a,
1664
         *       space_b_rank be the rank of space_b,
1665
         *
1666
         * Set all this up here.
1667
         */
1668
43.0k
        if (space1->extent.rank >= space2->extent.rank) {
1669
28.4k
            space_a = space1;
1670
28.4k
            space_b = space2;
1671
28.4k
        } /* end if */
1672
14.6k
        else {
1673
14.6k
            space_a = space2;
1674
14.6k
            space_b = space1;
1675
14.6k
        } /* end else */
1676
43.0k
        space_a_rank = space_a->extent.rank;
1677
43.0k
        space_b_rank = space_b->extent.rank;
1678
43.0k
        assert(space_a_rank >= space_b_rank);
1679
43.0k
        assert(space_b_rank > 0);
1680
1681
        /* Get selection type for both dataspaces */
1682
43.0k
        sel_a_type = H5S_GET_SELECT_TYPE(space_a);
1683
43.0k
        sel_b_type = H5S_GET_SELECT_TYPE(space_b);
1684
1685
        /* If selections aren't "none", compare their bounds */
1686
43.0k
        if (sel_a_type != H5S_SEL_NONE && sel_b_type != H5S_SEL_NONE) {
1687
43.0k
            hsize_t low_a[H5S_MAX_RANK];  /* Low bound of selection in dataspace a */
1688
43.0k
            hsize_t low_b[H5S_MAX_RANK];  /* Low bound of selection in dataspace b */
1689
43.0k
            hsize_t high_a[H5S_MAX_RANK]; /* High bound of selection in dataspace a */
1690
43.0k
            hsize_t high_b[H5S_MAX_RANK]; /* High bound of selection in dataspace b */
1691
1692
            /* Get low & high bounds for both dataspaces */
1693
43.0k
            if (H5S_SELECT_BOUNDS(space_a, low_a, high_a) < 0)
1694
0
                HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL,
1695
43.0k
                            "can't get selection bounds for first dataspace");
1696
43.0k
            if (H5S_SELECT_BOUNDS(space_b, low_b, high_b) < 0)
1697
0
                HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL,
1698
43.0k
                            "can't get selection bounds for second dataspace");
1699
1700
            /* Check that the range between the low & high bounds are the same */
1701
43.0k
            space_a_dim = (int)space_a_rank - 1;
1702
43.0k
            space_b_dim = (int)space_b_rank - 1;
1703
48.6k
            while (space_b_dim >= 0) {
1704
                /* Sanity check */
1705
44.3k
                assert(low_a[space_a_dim] <= high_a[space_a_dim]);
1706
44.3k
                assert(low_a[space_b_dim] <= high_a[space_b_dim]);
1707
1708
                /* Verify that the ranges are the same */
1709
44.3k
                if ((high_a[space_a_dim] - low_a[space_a_dim]) != (high_b[space_b_dim] - low_b[space_b_dim]))
1710
38.7k
                    HGOTO_DONE(false);
1711
1712
                /* Go to next dimension */
1713
5.59k
                space_a_dim--;
1714
5.59k
                space_b_dim--;
1715
5.59k
            } /* end while */
1716
1717
            /* Check that the rest of the ranges in space a are "flat" */
1718
5.02k
            while (space_a_dim >= 0) {
1719
                /* Sanity check */
1720
780
                assert(low_a[space_a_dim] <= high_a[space_a_dim]);
1721
1722
                /* This range should be flat to be the same in a lower dimension */
1723
780
                if (low_a[space_a_dim] != high_a[space_a_dim])
1724
85
                    HGOTO_DONE(false);
1725
1726
695
                space_a_dim--;
1727
695
            } /* end while */
1728
1729
            /* Check for a single block in each selection */
1730
4.24k
            if (H5S_SELECT_IS_SINGLE(space_a) && H5S_SELECT_IS_SINGLE(space_b)) {
1731
                /* If both selections are a single block and their bounds are
1732
                 * the same, then the selections are the same, even if the
1733
                 * selection types are different.
1734
                 */
1735
3.91k
                HGOTO_DONE(true);
1736
3.91k
            } /* end if */
1737
4.24k
        }     /* end if */
1738
1739
        /* If the dataspaces have the same selection type, use the selection's
1740
         * shape_same operator.
1741
         */
1742
324
        if (sel_a_type == sel_b_type)
1743
0
            ret_value = (*space_a->select.type->shape_same)(space_a, space_b);
1744
        /* Otherwise, iterate through all the blocks in the selection */
1745
324
        else {
1746
324
            hsize_t  start_a[H5S_MAX_RANK]; /* Start point of selection block in dataspace a */
1747
324
            hsize_t  start_b[H5S_MAX_RANK]; /* Start point of selection block in dataspace b */
1748
324
            hsize_t  end_a[H5S_MAX_RANK];   /* End point of selection block in dataspace a */
1749
324
            hsize_t  end_b[H5S_MAX_RANK];   /* End point of selection block in dataspace b */
1750
324
            hssize_t offset[H5S_MAX_RANK];  /* Offset of selection b blocks relative to selection a blocks */
1751
324
            bool     first_block = true;    /* Flag to indicate the first block */
1752
1753
            /* Allocate the selection iterators */
1754
324
            if (NULL == (iter_a = H5FL_MALLOC(H5S_sel_iter_t)))
1755
0
                HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate selection iterator");
1756
324
            if (NULL == (iter_b = H5FL_MALLOC(H5S_sel_iter_t)))
1757
0
                HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate selection iterator");
1758
1759
            /* Initialize iterator for each dataspace selection
1760
             * Use '0' for element size instead of actual element size to indicate
1761
             * that the selection iterator shouldn't be "flattened", since we
1762
             * aren't actually going to be doing I/O with the iterators.
1763
             */
1764
324
            if (H5S_select_iter_init(iter_a, space_a, (size_t)0, 0) < 0)
1765
0
                HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator a");
1766
324
            iter_a_init = true;
1767
324
            if (H5S_select_iter_init(iter_b, space_b, (size_t)0, 0) < 0)
1768
0
                HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator b");
1769
324
            iter_b_init = true;
1770
1771
            /* Iterate over all the blocks in each selection */
1772
324
            while (1) {
1773
324
                htri_t status_a, status_b; /* Status from next block checks */
1774
1775
                /* Get the current block for each selection iterator */
1776
324
                if (H5S_SELECT_ITER_BLOCK(iter_a, start_a, end_a) < 0)
1777
0
                    HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get iterator block a");
1778
324
                if (H5S_SELECT_ITER_BLOCK(iter_b, start_b, end_b) < 0)
1779
0
                    HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get iterator block b");
1780
1781
324
                space_a_dim = (int)space_a_rank - 1;
1782
324
                space_b_dim = (int)space_b_rank - 1;
1783
1784
                /* The first block only compares the sizes and sets the
1785
                 * relative offsets for later blocks
1786
                 */
1787
324
                if (first_block) {
1788
                    /* If the block sizes in the common dimensions from
1789
                     * each selection don't match, get out
1790
                     */
1791
324
                    while (space_b_dim >= 0) {
1792
324
                        if ((end_a[space_a_dim] - start_a[space_a_dim]) !=
1793
324
                            (end_b[space_b_dim] - start_b[space_b_dim]))
1794
324
                            HGOTO_DONE(false);
1795
1796
                        /* Set the relative locations of the selections */
1797
0
                        offset[space_a_dim] = (hssize_t)start_b[space_b_dim] - (hssize_t)start_a[space_a_dim];
1798
1799
0
                        space_a_dim--;
1800
0
                        space_b_dim--;
1801
0
                    } /* end while */
1802
1803
                    /* Similarly, if the block size in any dimension that appears only
1804
                     * in space_a is not equal to 1, get out.
1805
                     */
1806
0
                    while (space_a_dim >= 0) {
1807
0
                        if (start_a[space_a_dim] != end_a[space_a_dim])
1808
0
                            HGOTO_DONE(false);
1809
1810
0
                        space_a_dim--;
1811
0
                    } /* end while */
1812
1813
                    /* Reset "first block" flag */
1814
0
                    first_block = false;
1815
0
                } /* end if */
1816
                /* Check over the blocks for each selection */
1817
0
                else {
1818
                    /* For dimensions that space_a and space_b have in common: */
1819
0
                    while (space_b_dim >= 0) {
1820
                        /* Check if the blocks are in the same relative location */
1821
0
                        if ((hsize_t)((hssize_t)start_a[space_a_dim] + offset[space_a_dim]) !=
1822
0
                            start_b[space_b_dim])
1823
0
                            HGOTO_DONE(false);
1824
1825
                        /* If the block sizes from each selection doesn't match, get out */
1826
0
                        if ((end_a[space_a_dim] - start_a[space_a_dim]) !=
1827
0
                            (end_b[space_b_dim] - start_b[space_b_dim]))
1828
0
                            HGOTO_DONE(false);
1829
1830
0
                        space_a_dim--;
1831
0
                        space_b_dim--;
1832
0
                    } /* end while */
1833
1834
                    /* For dimensions that appear only in space_a: */
1835
0
                    while (space_a_dim >= 0) {
1836
                        /* If the block size isn't 1, get out */
1837
0
                        if (start_a[space_a_dim] != end_a[space_a_dim])
1838
0
                            HGOTO_DONE(false);
1839
1840
0
                        space_a_dim--;
1841
0
                    } /* end while */
1842
0
                }     /* end else */
1843
1844
                /* Check if we are able to advance to the next selection block */
1845
0
                if ((status_a = H5S_SELECT_ITER_HAS_NEXT_BLOCK(iter_a)) < 0)
1846
0
                    HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to check iterator block a");
1847
1848
0
                if ((status_b = H5S_SELECT_ITER_HAS_NEXT_BLOCK(iter_b)) < 0)
1849
0
                    HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to check iterator block b");
1850
1851
                /* Did we run out of blocks at the same time? */
1852
0
                if ((status_a == false) && (status_b == false))
1853
0
                    break;
1854
0
                else if (status_a != status_b)
1855
0
                    HGOTO_DONE(false);
1856
0
                else {
1857
                    /* Advance to next block in selection iterators */
1858
0
                    if (H5S_SELECT_ITER_NEXT_BLOCK(iter_a) < 0)
1859
0
                        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL,
1860
0
                                    "unable to advance to next iterator block a");
1861
1862
0
                    if (H5S_SELECT_ITER_NEXT_BLOCK(iter_b) < 0)
1863
0
                        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL,
1864
0
                                    "unable to advance to next iterator block b");
1865
0
                } /* end else */
1866
0
            }     /* end while */
1867
324
        }         /* end else */
1868
324
    }             /* end if */
1869
1870
43.0k
done:
1871
43.0k
    if (iter_a_init && H5S_SELECT_ITER_RELEASE(iter_a) < 0)
1872
0
        HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator a");
1873
43.0k
    if (iter_a)
1874
324
        iter_a = H5FL_FREE(H5S_sel_iter_t, iter_a);
1875
43.0k
    if (iter_b_init && H5S_SELECT_ITER_RELEASE(iter_b) < 0)
1876
0
        HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator b");
1877
43.0k
    if (iter_b)
1878
324
        iter_b = H5FL_FREE(H5S_sel_iter_t, iter_b);
1879
1880
43.0k
    FUNC_LEAVE_NOAPI(ret_value)
1881
43.0k
} /* end H5S_select_shape_same() */
1882
1883
/*--------------------------------------------------------------------------
1884
 NAME
1885
    H5Sselect_shape_same
1886
 PURPOSE
1887
    Check if two selections are the same shape
1888
 USAGE
1889
    htri_t H5Sselect_shape_same(space1_id, space2_id)
1890
        hid_t space1_id;         IN: ID of 1st Dataspace pointer to compare
1891
        hid_t space2_id;         IN: ID of 2nd Dataspace pointer to compare
1892
 RETURNS
1893
    true/false/FAIL
1894
 DESCRIPTION
1895
    Checks to see if the current selection in the dataspaces are the same
1896
    dimensionality and shape.
1897
    This is primarily used for reading the entire selection in one swoop.
1898
 GLOBAL VARIABLES
1899
 COMMENTS, BUGS, ASSUMPTIONS
1900
 EXAMPLES
1901
 REVISION LOG
1902
--------------------------------------------------------------------------*/
1903
htri_t
1904
H5Sselect_shape_same(hid_t space1_id, hid_t space2_id)
1905
0
{
1906
0
    H5S_t *space1, *space2; /* Dataspaces to compare */
1907
0
    htri_t ret_value;       /* Return value */
1908
1909
0
    FUNC_ENTER_API(FAIL)
1910
1911
0
    if (NULL == (space1 = (H5S_t *)H5I_object_verify(space1_id, H5I_DATASPACE)))
1912
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace");
1913
0
    if (NULL == (space2 = (H5S_t *)H5I_object_verify(space2_id, H5I_DATASPACE)))
1914
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace");
1915
1916
0
    if ((ret_value = H5S_select_shape_same(space1, space2)) < 0)
1917
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "can't compare selections");
1918
1919
0
done:
1920
0
    FUNC_LEAVE_API(ret_value)
1921
0
} /* end H5Sselect_shape_same() */
1922
1923
/*--------------------------------------------------------------------------
1924
 NAME
1925
    H5S_select_intersect_block
1926
 PURPOSE
1927
    Check if current selection intersects with a block
1928
 USAGE
1929
    htri_t H5S_select_intersect_block(space, start, end)
1930
        const H5S_t *space;      IN: Dataspace to compare
1931
        const hsize_t *start;    IN: Starting coordinate of block
1932
        const hsize_t *end;      IN: Opposite ("ending") coordinate of block
1933
 RETURNS
1934
    true / false / FAIL
1935
 DESCRIPTION
1936
    Checks to see if the current selection in the dataspace intersects with
1937
    the block given.
1938
 GLOBAL VARIABLES
1939
 COMMENTS, BUGS, ASSUMPTIONS
1940
    Assumes that start & end block bounds are _inclusive_, so start == end
1941
    value OK.
1942
1943
    This routine participates in the "Inlining C function pointers" pattern,
1944
    don't call it directly, use the appropriate macro defined in H5Sprivate.h.
1945
--------------------------------------------------------------------------*/
1946
htri_t
1947
H5S_select_intersect_block(H5S_t *space, const hsize_t *start, const hsize_t *end)
1948
0
{
1949
0
    htri_t ret_value = true; /* Return value */
1950
1951
0
    FUNC_ENTER_NOAPI(FAIL)
1952
1953
    /* Check args */
1954
0
    assert(space);
1955
0
    assert(start);
1956
0
    assert(end);
1957
1958
    /* If selections aren't "none", compare their bounds */
1959
0
    if (H5S_SEL_NONE != H5S_GET_SELECT_TYPE(space)) {
1960
0
        hsize_t  low[H5S_MAX_RANK];  /* Low bound of selection in dataspace */
1961
0
        hsize_t  high[H5S_MAX_RANK]; /* High bound of selection in dataspace */
1962
0
        unsigned u;                  /* Local index variable */
1963
1964
        /* Get low & high bounds for dataspace selection */
1965
0
        if (H5S_SELECT_BOUNDS(space, low, high) < 0)
1966
0
            HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get selection bounds for dataspace");
1967
1968
        /* Loop over selection bounds and block, checking for overlap */
1969
0
        for (u = 0; u < space->extent.rank; u++)
1970
            /* If selection bounds & block don't overlap, can leave now */
1971
0
            if (!H5_RANGE_OVERLAP(low[u], high[u], start[u], end[u]))
1972
0
                HGOTO_DONE(false);
1973
0
    } /* end if */
1974
1975
    /* Call selection type's intersect routine */
1976
0
    if ((ret_value = (*space->select.type->intersect_block)(space, start, end)) < 0)
1977
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "can't intersect block with selection");
1978
1979
0
done:
1980
0
    FUNC_LEAVE_NOAPI(ret_value)
1981
0
} /* end H5S_select_intersect_block() */
1982
1983
/*--------------------------------------------------------------------------
1984
 NAME
1985
    H5Sselect_intersect_block
1986
 PURPOSE
1987
    Check if current selection intersects with a block
1988
 USAGE
1989
    htri_t H5Sselect_intersect_block(space_id, start, end)
1990
        hid_t space1_id;         IN: ID of dataspace pointer to compare
1991
        const hsize_t *start;    IN: Starting coordinate of block
1992
        const hsize_t *end;      IN: Opposite ("ending") coordinate of block
1993
 RETURNS
1994
    true / false / FAIL
1995
 DESCRIPTION
1996
    Checks to see if the current selection in the dataspace intersects with
1997
    the block given.
1998
 GLOBAL VARIABLES
1999
 COMMENTS, BUGS, ASSUMPTIONS
2000
    Assumes that start & end block bounds are _inclusive_, so start == end
2001
    value OK.
2002
 EXAMPLES
2003
 REVISION LOG
2004
--------------------------------------------------------------------------*/
2005
htri_t
2006
H5Sselect_intersect_block(hid_t space_id, const hsize_t *start, const hsize_t *end)
2007
0
{
2008
0
    H5S_t   *space;            /* Dataspace to query */
2009
0
    unsigned u;                /* Local index value */
2010
0
    htri_t   ret_value = FAIL; /* Return value */
2011
2012
0
    FUNC_ENTER_API(FAIL)
2013
2014
    /* Check arguments */
2015
0
    if (NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
2016
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace");
2017
0
    if (NULL == start)
2018
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "block start array pointer is NULL");
2019
0
    if (NULL == end)
2020
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "block end array pointer is NULL");
2021
2022
    /* Range check start & end values */
2023
0
    for (u = 0; u < space->extent.rank; u++)
2024
0
        if (start[u] > end[u])
2025
0
            HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "block start[%u] (%llu) > end[%u] (%llu)", u,
2026
0
                        (unsigned long long)start[u], u, (unsigned long long)end[u]);
2027
2028
    /* Call internal routine to do comparison */
2029
0
    if ((ret_value = H5S_select_intersect_block(space, start, end)) < 0)
2030
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "can't compare selection and block");
2031
2032
0
done:
2033
0
    FUNC_LEAVE_API(ret_value)
2034
0
} /* end H5Sselect_intersect_block() */
2035
2036
/*--------------------------------------------------------------------------
2037
 NAME
2038
    H5S_select_construct_projection
2039
2040
 PURPOSE
2041
    Given a dataspace a of rank n with some selection, construct a new
2042
    dataspace b of rank m (m != n), with the selection in a being
2043
    topologically identical to that in b (as verified by
2044
    H5S_select_shape_same().
2045
2046
    This function exists, as some I/O code chokes on topologically
2047
    identical selections with different ranks.  At least to begin
2048
    with, we will deal with the issue by constructing projections
2049
    of the memory dataspace with ranks equaling those of the file
2050
    dataspace.
2051
2052
    Note that if m > n, it is possible that the starting point in the
2053
    buffer associated with the memory dataspace will have to be
2054
    adjusted to match the projected dataspace. In this case, the amount
2055
    of adjustment to be applied to the buffer will be returned via the
2056
    buf_adj parameter, if supplied.
2057
2058
 USAGE
2059
    htri_t H5S_select_construct_projection(base_space,
2060
                                           new_space_ptr,
2061
                                           new_space_rank,
2062
                                           element_size,
2063
                                           buf_adj)
2064
        const H5S_t *base_space;     IN: Ptr to Dataspace to project
2065
        H5S_t ** new_space_ptr;     OUT: Ptr to location in which to return
2066
                                         the address of the projected space
2067
        int new_space_rank;      IN: Rank of the projected space.
2068
        hsize_t element_size;        IN: size of each element in the selection
2069
        ptrdiff_t buf_adj;          OUT: amount of adjustment to be applied
2070
                                         to buffer associated with memory
2071
                                         dataspace
2072
2073
 RETURNS
2074
    Non-negative on success/Negative on failure.
2075
2076
 DESCRIPTION
2077
    Construct a new dataspace and associated selection which is a
2078
    projection of the supplied dataspace and associated selection into
2079
    the specified rank.  Return it in *new_space_ptr.
2080
2081
 GLOBAL VARIABLES
2082
 COMMENTS, BUGS, ASSUMPTIONS
2083
    The selection in the supplied base_space has thickness 1 in all
2084
    dimensions greater than new_space_rank.  Note that here we count
2085
    dimensions from the fastest changing coordinate to the slowest
2086
    changing changing coordinate.
2087
 EXAMPLES
2088
 REVISION LOG
2089
--------------------------------------------------------------------------*/
2090
herr_t
2091
H5S_select_construct_projection(H5S_t *base_space, H5S_t **new_space_ptr, unsigned new_space_rank,
2092
                                hsize_t element_size, ptrdiff_t *buf_adj)
2093
398
{
2094
398
    H5S_t   *new_space = NULL;                         /* New dataspace constructed */
2095
398
    hsize_t  base_space_dims[H5S_MAX_RANK];            /* Current dimensions of base dataspace */
2096
398
    hsize_t  base_space_maxdims[H5S_MAX_RANK];         /* Maximum dimensions of base dataspace */
2097
398
    int      sbase_space_rank;                         /* Signed # of dimensions of base dataspace */
2098
398
    unsigned base_space_rank;                          /* # of dimensions of base dataspace */
2099
398
    hsize_t  projected_space_element_offset = 0;       /* Offset of selected element in projected buffer */
2100
398
    herr_t   ret_value                      = SUCCEED; /* Return value */
2101
2102
398
    FUNC_ENTER_NOAPI(FAIL)
2103
2104
    /* Sanity checks */
2105
398
    assert(base_space != NULL);
2106
398
    assert((H5S_GET_EXTENT_TYPE(base_space) == H5S_SCALAR) ||
2107
398
           (H5S_GET_EXTENT_TYPE(base_space) == H5S_SIMPLE));
2108
398
    assert(new_space_ptr != NULL);
2109
398
    assert((new_space_rank != 0) || (H5S_GET_SELECT_NPOINTS(base_space) <= 1));
2110
398
    assert(new_space_rank <= H5S_MAX_RANK);
2111
398
    assert(element_size > 0);
2112
2113
    /* Get the extent info for the base dataspace */
2114
398
    if ((sbase_space_rank = H5S_get_simple_extent_dims(base_space, base_space_dims, base_space_maxdims)) < 0)
2115
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality of base space");
2116
398
    base_space_rank = (unsigned)sbase_space_rank;
2117
398
    assert(base_space_rank != new_space_rank);
2118
2119
    /* Check if projected space is scalar */
2120
398
    if (new_space_rank == 0) {
2121
24
        hssize_t npoints; /* Number of points selected */
2122
2123
        /* Retrieve the number of elements selected */
2124
24
        if ((npoints = (hssize_t)H5S_GET_SELECT_NPOINTS(base_space)) < 0)
2125
0
            HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get number of points selected");
2126
24
        assert(npoints <= 1);
2127
2128
        /* Create new scalar dataspace */
2129
24
        if (NULL == (new_space = H5S_create(H5S_SCALAR)))
2130
0
            HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create scalar dataspace");
2131
2132
        /* No need to register the dataspace(i.e. get an ID) as
2133
         * we will just be discarding it shortly.
2134
         */
2135
2136
        /* Selection for the new space will be either all or
2137
         * none, depending on whether the base space has 0 or
2138
         * 1 elements selected.
2139
         *
2140
         * Observe that the base space can't have more than
2141
         * one selected element, since its selection has the
2142
         * same shape as the file dataspace, and that data
2143
         * space is scalar.
2144
         */
2145
24
        if (1 == npoints) {
2146
            /* Assuming that the selection in the base dataspace is not
2147
             * empty, we must compute the offset of the selected item in
2148
             * the buffer associated with the base dataspace.
2149
             *
2150
             * Since the new space rank is zero, we know that the
2151
             * the base space must have rank at least 1 -- and
2152
             * hence it is a simple dataspace.  However, the
2153
             * selection, may be either point, hyperspace, or all.
2154
             *
2155
             */
2156
24
            if (H5S_SELECT_PROJECT_SCALAR(base_space, &projected_space_element_offset) < 0)
2157
0
                HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "unable to project scalar selection");
2158
24
        } /* end if */
2159
0
        else {
2160
0
            assert(0 == npoints);
2161
2162
0
            if (H5S_select_none(new_space) < 0)
2163
0
                HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't delete default selection");
2164
0
        }                                         /* end else */
2165
24
    }                                             /* end if */
2166
374
    else {                                        /* projected space must be simple */
2167
374
        hsize_t  new_space_dims[H5S_MAX_RANK];    /* Current dimensions for new dataspace */
2168
374
        hsize_t  new_space_maxdims[H5S_MAX_RANK]; /* Maximum dimensions for new dataspace */
2169
374
        unsigned rank_diff;                       /* Difference in ranks */
2170
2171
        /* Set up the dimensions of the new, projected dataspace.
2172
         *
2173
         * How we do this depends on whether we are projecting up into
2174
         * increased dimensions, or down into a reduced number of
2175
         * dimensions.
2176
         *
2177
         * If we are projecting up (the first half of the following
2178
         * if statement), we copy the dimensions of the base data
2179
         * space into the fastest changing dimensions of the new
2180
         * projected dataspace, and set the remaining dimensions to
2181
         * one.
2182
         *
2183
         * If we are projecting down (the second half of the following
2184
         * if statement), we just copy the dimensions with the most
2185
         * quickly changing dimensions into the dims for the projected
2186
         * data set.
2187
         *
2188
         * This works, because H5S_select_shape_same() will return
2189
         * true on selections of different rank iff:
2190
         *
2191
         * 1) the selection in the lower rank dataspace matches that
2192
         *    in the dimensions with the fastest changing indices in
2193
         *    the larger rank dataspace, and
2194
         *
2195
         * 2) the selection has thickness 1 in all ranks that appear
2196
         *    only in the higher rank dataspace (i.e. those with
2197
         *    more slowly changing indices).
2198
         */
2199
374
        if (new_space_rank > base_space_rank) {
2200
374
            hsize_t tmp_dim_size = 1; /* Temporary dimension value, for filling arrays */
2201
2202
            /* we must copy the dimensions of the base space into
2203
             * the fastest changing dimensions of the new space,
2204
             * and set the remaining dimensions to 1
2205
             */
2206
374
            rank_diff = new_space_rank - base_space_rank;
2207
374
            H5VM_array_fill(new_space_dims, &tmp_dim_size, sizeof(tmp_dim_size), rank_diff);
2208
374
            H5VM_array_fill(new_space_maxdims, &tmp_dim_size, sizeof(tmp_dim_size), rank_diff);
2209
374
            H5MM_memcpy(&new_space_dims[rank_diff], base_space_dims,
2210
374
                        sizeof(new_space_dims[0]) * base_space_rank);
2211
374
            H5MM_memcpy(&new_space_maxdims[rank_diff], base_space_maxdims,
2212
374
                        sizeof(new_space_maxdims[0]) * base_space_rank);
2213
374
        }      /* end if */
2214
0
        else { /* new_space_rank < base_space_rank */
2215
            /* we must copy the fastest changing dimension of the
2216
             * base space into the dimensions of the new space.
2217
             */
2218
0
            rank_diff = base_space_rank - new_space_rank;
2219
0
            H5MM_memcpy(new_space_dims, &base_space_dims[rank_diff],
2220
0
                        sizeof(new_space_dims[0]) * new_space_rank);
2221
0
            H5MM_memcpy(new_space_maxdims, &base_space_maxdims[rank_diff],
2222
0
                        sizeof(new_space_maxdims[0]) * new_space_rank);
2223
0
        } /* end else */
2224
2225
        /* now have the new space rank and dimensions set up --
2226
         * so we can create the new simple dataspace.
2227
         */
2228
374
        if (NULL == (new_space = H5S_create_simple(new_space_rank, new_space_dims, new_space_maxdims)))
2229
0
            HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace");
2230
2231
        /* No need to register the dataspace(i.e. get an ID) as
2232
         * we will just be discarding it shortly.
2233
         */
2234
2235
        /* If we get this far, we have successfully created the projected
2236
         * dataspace.  We must now project the selection in the base
2237
         * dataspace into the projected dataspace.
2238
         */
2239
374
        if (H5S_SELECT_PROJECT_SIMPLE(base_space, new_space, &projected_space_element_offset) < 0)
2240
0
            HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "unable to project simple selection");
2241
2242
        /* If we get this far, we have created the new dataspace, and projected
2243
         * the selection in the base dataspace into the new dataspace.
2244
         *
2245
         * If the base dataspace is simple, check to see if the
2246
         * offset_changed flag on the base selection has been set -- if so,
2247
         * project the offset into the new dataspace and set the
2248
         * offset_changed flag.
2249
         */
2250
374
        if (H5S_GET_EXTENT_TYPE(base_space) == H5S_SIMPLE && base_space->select.offset_changed) {
2251
0
            if (new_space_rank > base_space_rank) {
2252
0
                memset(new_space->select.offset, 0, sizeof(new_space->select.offset[0]) * rank_diff);
2253
0
                H5MM_memcpy(&new_space->select.offset[rank_diff], base_space->select.offset,
2254
0
                            sizeof(new_space->select.offset[0]) * base_space_rank);
2255
0
            } /* end if */
2256
0
            else
2257
0
                H5MM_memcpy(new_space->select.offset, &base_space->select.offset[rank_diff],
2258
0
                            sizeof(new_space->select.offset[0]) * new_space_rank);
2259
2260
            /* Propagate the offset changed flag into the new dataspace. */
2261
0
            new_space->select.offset_changed = true;
2262
0
        } /* end if */
2263
374
    }     /* end else */
2264
2265
    /* If we have done the projection correctly, the following assertion
2266
     * should hold.
2267
     */
2268
398
    assert(true == H5S_select_shape_same(base_space, new_space));
2269
2270
    /* load the address of the new space into *new_space_ptr */
2271
398
    *new_space_ptr = new_space;
2272
2273
    /* return the buffer adjustment amount if required */
2274
398
    if (buf_adj != NULL) {
2275
398
        if (new_space_rank < base_space_rank) {
2276
24
            *buf_adj = (ptrdiff_t)(projected_space_element_offset * element_size);
2277
24
        }
2278
374
        else
2279
            /* No adjustment necessary */
2280
374
            *buf_adj = 0;
2281
398
    }
2282
2283
398
done:
2284
    /* Cleanup on error */
2285
398
    if (ret_value < 0)
2286
0
        if (new_space && H5S_close(new_space) < 0)
2287
0
            HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace");
2288
2289
398
    FUNC_LEAVE_NOAPI(ret_value)
2290
398
} /* end H5S_select_construct_projection() */
2291
2292
/*--------------------------------------------------------------------------
2293
 NAME
2294
    H5S_select_fill
2295
 PURPOSE
2296
    Fill a selection in memory with a value
2297
 USAGE
2298
    herr_t H5S_select_fill(fill,fill_size,space,buf)
2299
        const void *fill;       IN: Pointer to fill value to use
2300
        size_t fill_size;       IN: Size of elements in memory buffer & size of
2301
                                    fill value
2302
        H5S_t *space;           IN: Dataspace describing memory buffer &
2303
                                    containing selection to use.
2304
        void *buf;              IN/OUT: Memory buffer to fill selection in
2305
 RETURNS
2306
    Non-negative on success/Negative on failure.
2307
 DESCRIPTION
2308
    Use the selection in the dataspace to fill elements in a memory buffer.
2309
 GLOBAL VARIABLES
2310
 COMMENTS, BUGS, ASSUMPTIONS
2311
    The memory buffer elements are assumed to have the same datatype as the
2312
    fill value being placed into them.
2313
 EXAMPLES
2314
 REVISION LOG
2315
--------------------------------------------------------------------------*/
2316
herr_t
2317
H5S_select_fill(const void *fill, size_t fill_size, H5S_t *space, void *_buf)
2318
0
{
2319
0
    H5S_sel_iter_t *iter      = NULL;    /* Selection iteration info */
2320
0
    bool            iter_init = false;   /* Selection iteration info has been initialized */
2321
0
    hsize_t        *off       = NULL;    /* Array to store sequence offsets */
2322
0
    size_t         *len       = NULL;    /* Array to store sequence lengths */
2323
0
    hssize_t        nelmts;              /* Number of elements in selection */
2324
0
    size_t          max_elem;            /* Total number of elements in selection */
2325
0
    herr_t          ret_value = SUCCEED; /* Return value */
2326
2327
0
    FUNC_ENTER_NOAPI(FAIL)
2328
2329
    /* Check args */
2330
0
    assert(fill);
2331
0
    assert(fill_size > 0);
2332
0
    assert(space);
2333
0
    assert(_buf);
2334
2335
    /* Allocate the selection iterator */
2336
0
    if (NULL == (iter = H5FL_MALLOC(H5S_sel_iter_t)))
2337
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate selection iterator");
2338
2339
    /* Initialize iterator */
2340
0
    if (H5S_select_iter_init(iter, space, fill_size, 0) < 0)
2341
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator");
2342
0
    iter_init = true; /* Selection iteration info has been initialized */
2343
2344
    /* Get the number of elements in selection */
2345
0
    if ((nelmts = (hssize_t)H5S_GET_SELECT_NPOINTS(space)) < 0)
2346
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't get number of elements selected");
2347
2348
    /* Compute the number of bytes to process */
2349
0
    H5_CHECKED_ASSIGN(max_elem, size_t, nelmts, hssize_t);
2350
2351
    /* Allocate the offset & length arrays */
2352
0
    if (NULL == (len = H5FL_SEQ_MALLOC(size_t, H5D_IO_VECTOR_SIZE)))
2353
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate length vector array");
2354
0
    if (NULL == (off = H5FL_SEQ_MALLOC(hsize_t, H5D_IO_VECTOR_SIZE)))
2355
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate offset vector array");
2356
2357
    /* Loop, while elements left in selection */
2358
0
    while (max_elem > 0) {
2359
0
        size_t nseq;     /* Number of sequences generated */
2360
0
        size_t curr_seq; /* Current sequence being worked on */
2361
0
        size_t nelem;    /* Number of elements used in sequences */
2362
2363
        /* Get the sequences of bytes */
2364
0
        if (H5S_SELECT_ITER_GET_SEQ_LIST(iter, (size_t)H5D_IO_VECTOR_SIZE, max_elem, &nseq, &nelem, off,
2365
0
                                         len) < 0)
2366
0
            HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed");
2367
2368
        /* Loop over sequences */
2369
0
        for (curr_seq = 0; curr_seq < nseq; curr_seq++) {
2370
0
            uint8_t *buf; /* Current location in buffer */
2371
2372
            /* Get offset in memory buffer */
2373
0
            buf = (uint8_t *)_buf + off[curr_seq];
2374
2375
            /* Fill each sequence in memory with fill value */
2376
0
            assert((len[curr_seq] % fill_size) == 0);
2377
0
            H5VM_array_fill(buf, fill, fill_size, (len[curr_seq] / fill_size));
2378
0
        } /* end for */
2379
2380
        /* Decrement number of elements left to process */
2381
0
        max_elem -= nelem;
2382
0
    } /* end while */
2383
2384
0
done:
2385
    /* Release resources, if allocated */
2386
0
    if (len)
2387
0
        len = H5FL_SEQ_FREE(size_t, len);
2388
0
    if (off)
2389
0
        off = H5FL_SEQ_FREE(hsize_t, off);
2390
2391
    /* Release selection iterator */
2392
0
    if (iter_init && H5S_SELECT_ITER_RELEASE(iter) < 0)
2393
0
        HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator");
2394
0
    if (iter)
2395
0
        iter = H5FL_FREE(H5S_sel_iter_t, iter);
2396
2397
0
    FUNC_LEAVE_NOAPI(ret_value)
2398
0
} /* end H5S_select_fill() */
2399
2400
/*--------------------------------------------------------------------------
2401
 NAME
2402
    H5S_select_project_intersection
2403
2404
 PURPOSE
2405
    Projects the intersection of of the selections of src_space and
2406
    src_intersect_space within the selection of src_space as a selection
2407
    within the selection of dst_space
2408
2409
 USAGE
2410
    herr_t H5S_select_project_intersection(src_space,dst_space,src_intersect_space,proj_space,share_selection)
2411
        H5S_t *src_space;       IN: Selection that is mapped to dst_space, and intersected with
2412
src_intersect_space H5S_t *dst_space;       IN: Selection that is mapped to src_space H5S_t
2413
*src_intersect_space; IN: Selection whose intersection with src_space is projected to dst_space to obtain the
2414
result H5S_t **new_space_ptr;  OUT: Will contain the result (intersection of src_intersect_space and src_space
2415
projected from src_space to dst_space) after the operation bool share_selection; IN: Whether we are allowed
2416
to share structures inside dst_space with proj_space
2417
2418
 RETURNS
2419
    Non-negative on success/Negative on failure.
2420
2421
 DESCRIPTION
2422
    Projects the intersection of of the selections of src_space and
2423
    src_intersect_space within the selection of src_space as a selection
2424
    within the selection of dst_space.  The result is placed in the
2425
    selection of new_space_ptr.
2426
2427
 GLOBAL VARIABLES
2428
 COMMENTS, BUGS, ASSUMPTIONS
2429
 EXAMPLES
2430
 REVISION LOG
2431
--------------------------------------------------------------------------*/
2432
herr_t
2433
H5S_select_project_intersection(H5S_t *src_space, H5S_t *dst_space, H5S_t *src_intersect_space,
2434
                                H5S_t **new_space_ptr, bool share_selection)
2435
0
{
2436
0
    H5S_t          *new_space               = NULL;    /* New dataspace constructed */
2437
0
    H5S_t          *tmp_src_intersect_space = NULL;    /* Temporary SIS converted from points->hyperslabs */
2438
0
    H5S_sel_iter_t *ss_iter                 = NULL;    /* Selection iterator for src_space */
2439
0
    bool            ss_iter_init            = false;   /* Whether ss_iter has been initialized */
2440
0
    H5S_sel_iter_t *ds_iter                 = NULL;    /* Selection iterator for dst_space */
2441
0
    bool            ds_iter_init            = false;   /* Whether ds_iter has been initialized */
2442
0
    herr_t          ret_value               = SUCCEED; /* Return value */
2443
2444
0
    FUNC_ENTER_NOAPI(FAIL)
2445
2446
    /* Sanity checks */
2447
0
    assert(src_space);
2448
0
    assert(dst_space);
2449
0
    assert(src_intersect_space);
2450
0
    assert(new_space_ptr);
2451
0
    assert(H5S_GET_SELECT_NPOINTS(src_space) == H5S_GET_SELECT_NPOINTS(dst_space));
2452
0
    assert(H5S_GET_EXTENT_NDIMS(src_space) == H5S_GET_EXTENT_NDIMS(src_intersect_space));
2453
2454
0
    if (NULL == (ss_iter = H5FL_CALLOC(H5S_sel_iter_t)))
2455
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate selection iterator");
2456
0
    if (NULL == (ds_iter = H5FL_CALLOC(H5S_sel_iter_t)))
2457
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate selection iterator");
2458
2459
    /* Create new space, using dst extent.  Start with "all" selection. */
2460
0
    if (NULL == (new_space = H5S_create(H5S_SIMPLE)))
2461
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create output dataspace");
2462
0
    if (H5S__extent_copy_real(&new_space->extent, &dst_space->extent, true) < 0)
2463
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy destination space extent");
2464
2465
    /* If the intersecting space is "all", the intersection must be equal to the
2466
     * source space and the projection must be equal to the destination space */
2467
0
    if (H5S_GET_SELECT_TYPE(src_intersect_space) == H5S_SEL_ALL) {
2468
        /* Copy the destination selection. */
2469
0
        if (H5S_select_copy(new_space, dst_space, false) < 0)
2470
0
            HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy destination space selection");
2471
0
    } /* end if */
2472
    /* If any of the selections contain no elements, the projection must be
2473
     * "none" */
2474
0
    else if ((H5S_GET_SELECT_NPOINTS(src_intersect_space) == 0) || (H5S_GET_SELECT_NPOINTS(src_space) == 0) ||
2475
0
             (H5S_GET_SELECT_NPOINTS(dst_space) == 0)) {
2476
        /* Change to "none" selection */
2477
0
        if (H5S_select_none(new_space) < 0)
2478
0
            HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection");
2479
0
    } /* end if */
2480
0
    else {
2481
        /* Handle scalar dataspaces.  It should not be possible for the source
2482
         * intersect space or the source space to be scalar since scalar spaces
2483
         * only support all or none selections, and both of those cases are
2484
         * covered above, and the source intersect space must have the same
2485
         * rank, so it also cannot be scalar, as scalar dataspaces have a rank
2486
         * of 0. */
2487
0
        assert(H5S_GET_EXTENT_TYPE(src_space) != H5S_SCALAR);
2488
0
        assert(H5S_GET_EXTENT_TYPE(src_intersect_space) != H5S_SCALAR);
2489
2490
        /* Check for scalar dst_space.  In this case we simply check if the
2491
         * (single) point selected in src_space intersects src_intersect_space,
2492
         * if so select all in new_space, otherwise select none. */
2493
0
        if (H5S_GET_EXTENT_TYPE(dst_space) == H5S_SCALAR) {
2494
0
            hsize_t coords_start[H5S_MAX_RANK];
2495
0
            hsize_t coords_end[H5S_MAX_RANK];
2496
0
            htri_t  intersect;
2497
2498
            /* Get source space bounds.  Should be a single point. */
2499
0
            if (H5S_SELECT_BOUNDS(src_space, coords_start, coords_end) < 0)
2500
0
                HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get source space bounds");
2501
0
            assert(0 == memcmp(coords_start, coords_end,
2502
0
                               H5S_GET_EXTENT_NDIMS(src_space) * sizeof(coords_start[0])));
2503
2504
            /* Check for intersection */
2505
0
            if ((intersect = H5S_SELECT_INTERSECT_BLOCK(src_intersect_space, coords_start, coords_end)) < 0)
2506
0
                HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "can't check for intersection");
2507
2508
            /* Select all or none as appropriate */
2509
0
            if (intersect) {
2510
0
                if (H5S_select_all(new_space, true) < 0)
2511
0
                    HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't select all");
2512
0
            } /* end if */
2513
0
            else if (H5S_select_none(new_space) < 0)
2514
0
                HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection");
2515
0
        } /* end if */
2516
0
        else {
2517
            /* If the source intersect space is a point selection, convert it to a
2518
             * hyperslab (discarding ordering).  We can get away with this because
2519
             * the order does not matter for the source intersect space */
2520
            /* Maybe we should just leave it as a point selection for the point by
2521
             * point algorithm?  The search through the selection in
2522
             * H5S_SELECT_INTERSECT_BLOCK will likely be O(N) either way.  -NAF */
2523
0
            if (H5S_GET_SELECT_TYPE(src_intersect_space) == H5S_SEL_POINTS) {
2524
0
                H5S_pnt_node_t *curr_pnt = src_intersect_space->select.sel_info.pnt_lst->head;
2525
2526
                /* Create dataspace and copy extent */
2527
0
                if (NULL == (tmp_src_intersect_space = H5S_create(H5S_SIMPLE)))
2528
0
                    HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL,
2529
0
                                "unable to create temporary source intersect dataspace");
2530
0
                if (H5S__extent_copy_real(&tmp_src_intersect_space->extent, &src_intersect_space->extent,
2531
0
                                          false) < 0)
2532
0
                    HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL,
2533
0
                                "unable to copy source intersect space extent");
2534
2535
                /* Iterate over points */
2536
0
                for (curr_pnt = src_intersect_space->select.sel_info.pnt_lst->head; curr_pnt;
2537
0
                     curr_pnt = curr_pnt->next)
2538
                    /* Add point to hyperslab selection */
2539
0
                    if (H5S_hyper_add_span_element(tmp_src_intersect_space, src_intersect_space->extent.rank,
2540
0
                                                   curr_pnt->pnt) < 0)
2541
0
                        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL,
2542
0
                                    "can't add point to temporary dataspace selection");
2543
2544
                /* Redirect local src_intersect_space pointer (will not affect
2545
                 * calling function) */
2546
0
                src_intersect_space = tmp_src_intersect_space;
2547
0
            } /* end for */
2548
2549
            /* By this point, src_intersect_space must be a hyperslab selection */
2550
0
            assert(H5S_GET_SELECT_TYPE(src_intersect_space) == H5S_SEL_HYPERSLABS);
2551
2552
            /* If either the source space or the destination space is a point
2553
             * selection, iterate element by element */
2554
0
            if ((H5S_GET_SELECT_TYPE(src_space) == H5S_SEL_POINTS) ||
2555
0
                (H5S_GET_SELECT_TYPE(dst_space) == H5S_SEL_POINTS)) {
2556
0
                hsize_t coords[H5S_MAX_RANK];
2557
0
                htri_t  intersect;
2558
2559
                /* Start with "none" selection */
2560
0
                if (H5S_select_none(new_space) < 0)
2561
0
                    HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection");
2562
2563
                /* Initialize iterators */
2564
0
                if (H5S_select_iter_init(ss_iter, src_space, 1, H5S_SEL_ITER_SHARE_WITH_DATASPACE) < 0)
2565
0
                    HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL,
2566
0
                                "can't initialize source space selection iterator");
2567
0
                ss_iter_init = true;
2568
0
                if (H5S_select_iter_init(ds_iter, dst_space, 1, H5S_SEL_ITER_SHARE_WITH_DATASPACE) < 0)
2569
0
                    HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL,
2570
0
                                "can't initialize destination space selection iterator");
2571
0
                ds_iter_init = true;
2572
2573
                /* Iterate over points */
2574
0
                do {
2575
0
                    assert(ss_iter->elmt_left > 0);
2576
0
                    assert(ss_iter->elmt_left > 0);
2577
2578
                    /* Get SS coords */
2579
0
                    if (H5S_SELECT_ITER_COORDS(ss_iter, coords) < 0)
2580
0
                        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL,
2581
0
                                    "can't get source selection coordinates");
2582
2583
                    /* Check for intersection */
2584
0
                    if ((intersect = H5S_SELECT_INTERSECT_BLOCK(src_intersect_space, coords, coords)) < 0)
2585
0
                        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "can't check for intersection");
2586
2587
                    /* Add point if it intersects */
2588
0
                    if (intersect) {
2589
                        /* Get DS coords */
2590
0
                        if (H5S_SELECT_ITER_COORDS(ds_iter, coords) < 0)
2591
0
                            HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL,
2592
0
                                        "can't get destination selection coordinates");
2593
2594
                        /* Add point to new_space */
2595
0
                        if (H5S_select_elements(new_space, H5S_SELECT_APPEND, 1, coords) < 0)
2596
0
                            HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL,
2597
0
                                        "can't add point to new selection");
2598
0
                    } /* end if */
2599
2600
                    /* Advance iterators */
2601
0
                    if (H5S_SELECT_ITER_NEXT(ss_iter, 1) < 0)
2602
0
                        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL,
2603
0
                                    "can't advance source selection iterator");
2604
0
                    ss_iter->elmt_left--;
2605
0
                    if (H5S_SELECT_ITER_NEXT(ds_iter, 1) < 0)
2606
0
                        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL,
2607
0
                                    "can't advance destination selection iterator");
2608
0
                    ds_iter->elmt_left--;
2609
0
                } while (ss_iter->elmt_left > 0);
2610
0
                assert(H5S_SELECT_ITER_NELMTS(ds_iter) == 0);
2611
0
            } /* end if */
2612
0
            else {
2613
0
                assert(H5S_GET_SELECT_TYPE(src_space) != H5S_SEL_NONE);
2614
0
                assert(H5S_GET_SELECT_TYPE(dst_space) != H5S_SEL_NONE);
2615
2616
                /* Source and destination selections are all or hyperslab,
2617
                 * intersecting selection is hyperslab.  Call the hyperslab routine
2618
                 * to project to another hyperslab selection. */
2619
0
                if (H5S__hyper_project_intersection(src_space, dst_space, src_intersect_space, new_space,
2620
0
                                                    share_selection) < 0)
2621
0
                    HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL,
2622
0
                                "can't project hyperslab onto destination selection");
2623
0
            } /* end else */
2624
0
        }     /* end else */
2625
0
    }         /* end else */
2626
2627
    /* load the address of the new space into *new_space_ptr */
2628
0
    *new_space_ptr = new_space;
2629
2630
0
done:
2631
    /* Cleanup on error */
2632
0
    if (ret_value < 0)
2633
0
        if (new_space && H5S_close(new_space) < 0)
2634
0
            HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace");
2635
2636
    /* General cleanup */
2637
0
    if (tmp_src_intersect_space && H5S_close(tmp_src_intersect_space) < 0)
2638
0
        HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release temporary dataspace");
2639
0
    if (ss_iter_init && H5S_SELECT_ITER_RELEASE(ss_iter) < 0)
2640
0
        HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release source selection iterator");
2641
0
    if (ds_iter_init && H5S_SELECT_ITER_RELEASE(ds_iter) < 0)
2642
0
        HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release destination selection iterator");
2643
2644
0
    ss_iter = H5FL_FREE(H5S_sel_iter_t, ss_iter);
2645
0
    ds_iter = H5FL_FREE(H5S_sel_iter_t, ds_iter);
2646
2647
0
    FUNC_LEAVE_NOAPI(ret_value)
2648
0
} /* end H5S_select_project_intersection() */
2649
2650
/*--------------------------------------------------------------------------
2651
 NAME
2652
    H5Sselect_project_intersection
2653
2654
 PURPOSE
2655
    Projects the intersection of of the selections of src_space_id and
2656
    src_intersect_space_id within the selection of src_space_id as a
2657
    selection within the selection of dst_space_id.
2658
2659
 USAGE
2660
    hid_t H5Sselect_project_intersection(src_space_id,dst_space_d,src_intersect_space_id)
2661
        hid_t src_space_id;         IN: Selection that is mapped to dst_space_id, and intersected with
2662
src_intersect_space_id hid_t dst_space_id;         IN: Selection that is mapped to src_space_id hid_t
2663
src_intersect_space_id; IN: Selection whose intersection with src_space_id is projected to dst_space_id to
2664
obtain the result
2665
2666
 RETURNS
2667
    A dataspace with a selection equal to the intersection of
2668
    src_intersect_space_id and src_space_id projected from src_space to
2669
    dst_space on success, negative on failure.
2670
2671
 DESCRIPTION
2672
    Projects the intersection of of the selections of src_space and
2673
    src_intersect_space within the selection of src_space as a selection
2674
    within the selection of dst_space.  The result is placed in the
2675
    selection of new_space_ptr.
2676
2677
 GLOBAL VARIABLES
2678
 COMMENTS, BUGS, ASSUMPTIONS
2679
 EXAMPLES
2680
 REVISION LOG
2681
--------------------------------------------------------------------------*/
2682
hid_t
2683
H5Sselect_project_intersection(hid_t src_space_id, hid_t dst_space_id, hid_t src_intersect_space_id)
2684
0
{
2685
0
    H5S_t *src_space, *dst_space, *src_intersect_space; /* Input dataspaces */
2686
0
    H5S_t *proj_space = NULL;                           /* Output dataspace */
2687
0
    hid_t  ret_value;                                   /* Return value */
2688
2689
0
    FUNC_ENTER_API(H5I_INVALID_HID)
2690
2691
    /* Check args */
2692
0
    if (NULL == (src_space = (H5S_t *)H5I_object_verify(src_space_id, H5I_DATASPACE)))
2693
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace");
2694
0
    if (NULL == (dst_space = (H5S_t *)H5I_object_verify(dst_space_id, H5I_DATASPACE)))
2695
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace");
2696
0
    if (NULL == (src_intersect_space = (H5S_t *)H5I_object_verify(src_intersect_space_id, H5I_DATASPACE)))
2697
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace");
2698
2699
    /* Check numbers of points selected matches in source and destination */
2700
0
    if (H5S_GET_SELECT_NPOINTS(src_space) != H5S_GET_SELECT_NPOINTS(dst_space))
2701
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, H5I_INVALID_HID,
2702
0
                    "number of points selected in source space does not match that in destination space");
2703
2704
    /* Check numbers of dimensions matches in source and source intersect spaces
2705
     */
2706
0
    if (H5S_GET_EXTENT_NDIMS(src_space) != H5S_GET_EXTENT_NDIMS(src_intersect_space))
2707
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, H5I_INVALID_HID,
2708
0
                    "rank of source space does not match rank of source intersect space");
2709
2710
    /* Perform operation */
2711
0
    if (H5S_select_project_intersection(src_space, dst_space, src_intersect_space, &proj_space, false) < 0)
2712
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTCLIP, H5I_INVALID_HID, "can't project dataspace intersection");
2713
2714
    /* Register */
2715
0
    if ((ret_value = H5I_register(H5I_DATASPACE, proj_space, true)) < 0)
2716
0
        HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace ID");
2717
2718
0
done:
2719
0
    if (ret_value < 0)
2720
0
        if (proj_space && H5S_close(proj_space) < 0)
2721
0
            HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, H5I_INVALID_HID, "unable to release dataspace");
2722
2723
0
    FUNC_LEAVE_API(ret_value)
2724
0
} /* end H5Sselect_project_intersection() */
2725
2726
/*--------------------------------------------------------------------------
2727
 NAME
2728
    H5S_select_subtract
2729
2730
 PURPOSE
2731
    Subtract one selection from another
2732
2733
 USAGE
2734
    herr_t H5S_select_subtract(space,subtract_space)
2735
        H5S_t *space;           IN/OUT: Selection to be operated on
2736
        H5S_t *subtract_space;  IN: Selection that will be subtracted from space
2737
2738
 RETURNS
2739
    Non-negative on success/Negative on failure.
2740
2741
 DESCRIPTION
2742
    Removes any and all portions of space that are also present in
2743
    subtract_space.  In essence, performs an A_NOT_B operation with the
2744
    two selections.
2745
2746
 GLOBAL VARIABLES
2747
 COMMENTS, BUGS, ASSUMPTIONS
2748
 EXAMPLES
2749
 REVISION LOG
2750
--------------------------------------------------------------------------*/
2751
herr_t
2752
H5S_select_subtract(H5S_t *space, H5S_t *subtract_space)
2753
0
{
2754
0
    herr_t ret_value = SUCCEED; /* Return value */
2755
2756
0
    FUNC_ENTER_NOAPI(FAIL)
2757
2758
    /* Sanity checks */
2759
0
    assert(space);
2760
0
    assert(subtract_space);
2761
2762
    /* If either space is using the none selection, then we do not need to do
2763
     * anything */
2764
0
    if ((space->select.type->type != H5S_SEL_NONE) && (subtract_space->select.type->type != H5S_SEL_NONE)) {
2765
        /* If subtract_space is using the all selection, set space to none */
2766
0
        if (subtract_space->select.type->type == H5S_SEL_ALL) {
2767
            /* Change to "none" selection */
2768
0
            if (H5S_select_none(space) < 0)
2769
0
                HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection");
2770
0
        } /* end if */
2771
        /* If either selection is a point selection, fail currently */
2772
0
        else if ((subtract_space->select.type->type == H5S_SEL_POINTS) ||
2773
0
                 (space->select.type->type == H5S_SEL_POINTS)) {
2774
0
            HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "point selections not currently supported");
2775
0
        } /* end if */
2776
0
        else {
2777
            /* Check for all selection in space, convert to hyperslab */
2778
0
            if (space->select.type->type == H5S_SEL_ALL) {
2779
                /* Convert current "all" selection to "real" hyperslab selection */
2780
                /* Then allow operation to proceed */
2781
0
                hsize_t  tmp_start[H5S_MAX_RANK];  /* Temporary start information */
2782
0
                hsize_t  tmp_stride[H5S_MAX_RANK]; /* Temporary stride information */
2783
0
                hsize_t  tmp_count[H5S_MAX_RANK];  /* Temporary count information */
2784
0
                hsize_t  tmp_block[H5S_MAX_RANK];  /* Temporary block information */
2785
0
                unsigned u;                        /* Local index variable */
2786
2787
                /* Fill in temporary information for the dimensions */
2788
0
                for (u = 0; u < space->extent.rank; u++) {
2789
0
                    tmp_start[u]  = 0;
2790
0
                    tmp_stride[u] = 1;
2791
0
                    tmp_count[u]  = 1;
2792
0
                    tmp_block[u]  = space->extent.size[u];
2793
0
                } /* end for */
2794
2795
                /* Convert to hyperslab selection */
2796
0
                if (H5S_select_hyperslab(space, H5S_SELECT_SET, tmp_start, tmp_stride, tmp_count, tmp_block) <
2797
0
                    0)
2798
0
                    HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection");
2799
0
            } /* end if */
2800
2801
0
            assert(space->select.type->type == H5S_SEL_HYPERSLABS);
2802
0
            assert(subtract_space->select.type->type == H5S_SEL_HYPERSLABS);
2803
2804
            /* Both spaces are now hyperslabs, perform the operation */
2805
0
            if (H5S__modify_select(space, H5S_SELECT_NOTB, subtract_space) < 0)
2806
0
                HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't subtract hyperslab");
2807
0
        } /* end else */
2808
0
    }     /* end if */
2809
2810
0
done:
2811
0
    FUNC_LEAVE_NOAPI(ret_value)
2812
0
} /* end H5S_select_subtract() */
2813
2814
/*--------------------------------------------------------------------------
2815
 NAME
2816
    H5Ssel_iter_create
2817
 PURPOSE
2818
    Create a dataspace selection iterator for a dataspace's selection
2819
 USAGE
2820
    hid_t H5Ssel_iter_create(space,elmt_size,flags)
2821
        hid_t   space;     IN: ID of the dataspace with selection to iterate over
2822
 RETURNS
2823
    Valid dataspace selection iterator ID on success, H5I_INVALID_HID on failure
2824
 DESCRIPTION
2825
    Creates a selection iterator and initializes it to start at the first
2826
    element selected in the dataspace.
2827
 PROGRAMMER
2828
 GLOBAL VARIABLES
2829
 COMMENTS, BUGS, ASSUMPTIONS
2830
 EXAMPLES
2831
 REVISION LOG
2832
--------------------------------------------------------------------------*/
2833
hid_t
2834
H5Ssel_iter_create(hid_t space_id, size_t elmt_size, unsigned flags)
2835
0
{
2836
0
    H5S_t          *space;     /* Dataspace with selection to iterate over */
2837
0
    H5S_sel_iter_t *sel_iter;  /* Selection iterator created */
2838
0
    hid_t           ret_value; /* Return value */
2839
2840
0
    FUNC_ENTER_API(H5I_INVALID_HID)
2841
2842
    /* Check args */
2843
0
    if (NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
2844
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace");
2845
0
    if (elmt_size == 0)
2846
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, H5I_INVALID_HID, "element size must be greater than 0");
2847
0
    if (flags != (flags & H5S_SEL_ITER_ALL_PUBLIC_FLAGS))
2848
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, H5I_INVALID_HID, "invalid selection iterator flag");
2849
2850
    /* Allocate the iterator */
2851
0
    if (NULL == (sel_iter = H5FL_MALLOC(H5S_sel_iter_t)))
2852
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, H5I_INVALID_HID, "can't allocate selection iterator");
2853
2854
    /* Add flag to indicate that this iterator is from an API call */
2855
0
    flags |= H5S_SEL_ITER_API_CALL;
2856
2857
    /* Initialize the selection iterator */
2858
0
    if (H5S_select_iter_init(sel_iter, space, elmt_size, flags) < 0)
2859
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, H5I_INVALID_HID, "unable to initialize selection iterator");
2860
2861
    /* Register */
2862
0
    if ((ret_value = H5I_register(H5I_SPACE_SEL_ITER, sel_iter, true)) < 0)
2863
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTREGISTER, H5I_INVALID_HID,
2864
0
                    "unable to register dataspace selection iterator ID");
2865
2866
0
done:
2867
0
    FUNC_LEAVE_API(ret_value)
2868
0
} /* end H5Ssel_iter_create() */
2869
2870
/*--------------------------------------------------------------------------
2871
 NAME
2872
    H5Ssel_iter_get_seq_list
2873
 PURPOSE
2874
    Retrieve a list of offset / length sequences for the elements in an iterator
2875
 USAGE
2876
    herr_t H5Ssel_iter_get_seq_list(sel_iter_id, maxseq, maxbytes, nseq, nbytes, off, len)
2877
        hid_t   sel_iter_id;  IN: ID of the dataspace selection iterator to retrieve sequence from
2878
        size_t  maxseq;       IN: Max. # of sequences to retrieve
2879
        size_t  maxelmts;     IN: Max. # of elements to retrieve in sequences
2880
        size_t *nseq;         OUT: # of sequences retrieved
2881
        size_t *nelmts;       OUT: # of elements retrieved, in all sequences
2882
        hsize_t *off;         OUT: Array of sequence offsets
2883
        size_t *len;          OUT: Array of sequence lengths
2884
 RETURNS
2885
    Non-negative on success / Negative on failure
2886
 DESCRIPTION
2887
    Retrieve a list of offset / length pairs (a list of "sequences") matching
2888
    the selected elements for an iterator, according to the iteration order for
2889
    the iterator.  The lengths returned are in _bytes_, not elements.
2890
2891
    Note that the iteration order for "all" and "hyperslab" selections is
2892
    row-major (i.e. "C-ordered"), but the iteration order for "point"
2893
    selections is "in order selected", unless the H5S_SEL_ITER_GET_SEQ_LIST_SORTED
2894
    flag is passed to H5Sset_iter_create for a point selection.
2895
2896
    MAXSEQ and MAXELMTS specify the most sequences or bytes possible to
2897
    place into the OFF and LEN arrays. *NSEQ and *NELMTS return the actual
2898
    number of sequences and bytes put into the arrays.
2899
2900
    Each call to H5Ssel_iter_get_seq_list() will retrieve the next set
2901
    of sequences for the selection being iterated over.
2902
2903
    The total number of bytes possible to retrieve from a selection iterator
2904
    is the 'elmt_size' passed to H5Ssel_iter_create multiplied by the number
2905
    of elements selected in the dataspace the iterator was created from
2906
    (which can be retrieved with H5Sget_select_npoints).  When there are no
2907
    further sequences of elements to retrieve, calls to this routine will
2908
    set *NSEQ and *NELMTS to zero.
2909
 PROGRAMMER
2910
 GLOBAL VARIABLES
2911
 COMMENTS, BUGS, ASSUMPTIONS
2912
 EXAMPLES
2913
 REVISION LOG
2914
--------------------------------------------------------------------------*/
2915
herr_t
2916
H5Ssel_iter_get_seq_list(hid_t sel_iter_id, size_t maxseq, size_t maxelmts, size_t *nseq /*out*/,
2917
                         size_t *nelmts /*out*/, hsize_t *off /*out*/, size_t *len /*out*/)
2918
0
{
2919
0
    H5S_sel_iter_t *sel_iter;            /* Dataspace selection iterator to operate on */
2920
0
    herr_t          ret_value = SUCCEED; /* Return value */
2921
2922
0
    FUNC_ENTER_API(FAIL)
2923
2924
    /* Check args */
2925
0
    if (NULL == (sel_iter = (H5S_sel_iter_t *)H5I_object_verify(sel_iter_id, H5I_SPACE_SEL_ITER)))
2926
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace selection iterator");
2927
0
    if (NULL == nseq)
2928
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "'nseq' pointer is NULL");
2929
0
    if (NULL == nelmts)
2930
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "'nbytes' pointer is NULL");
2931
0
    if (NULL == off)
2932
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "offset array pointer is NULL");
2933
0
    if (NULL == len)
2934
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "length array pointer is NULL");
2935
2936
    /* Get the sequences of bytes */
2937
0
    if (maxseq > 0 && maxelmts > 0 && sel_iter->elmt_left > 0) {
2938
0
        if (H5S_SELECT_ITER_GET_SEQ_LIST(sel_iter, maxseq, maxelmts, nseq, nelmts, off, len) < 0)
2939
0
            HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "sequence length generation failed");
2940
0
    } /* end if */
2941
0
    else
2942
0
        *nseq = *nelmts = 0;
2943
2944
0
done:
2945
0
    FUNC_LEAVE_API(ret_value)
2946
0
} /* end H5Ssel_iter_get_seq_list() */
2947
2948
/*--------------------------------------------------------------------------
2949
 NAME
2950
    H5S_select_contig_block
2951
2952
 PURPOSE
2953
    Determines if a selection is a single contiguous block, and returns the
2954
    offset and length (in elements) if it is
2955
2956
 USAGE
2957
    herr_t H5S_select_contig_block(space, is_contig, off, len)
2958
        H5S_t   *space;      IN: Selection to check
2959
        bool *is_contig;  OUT: Whether the selection is contiguous
2960
        hsize_t *off;        OUT: Offset of selection
2961
        size_t  *len;        OUT: Length of selection
2962
2963
 RETURNS
2964
    Non-negative on success/Negative on failure.
2965
2966
 DESCRIPTION
2967
    Determines if a selection is a single contiguous block, and returns the
2968
    offset and length (in elements) if it is.
2969
2970
 GLOBAL VARIABLES
2971
 COMMENTS, BUGS, ASSUMPTIONS
2972
 EXAMPLES
2973
 REVISION LOG
2974
--------------------------------------------------------------------------*/
2975
herr_t
2976
H5S_select_contig_block(H5S_t *space, bool *is_contig, hsize_t *off, size_t *len)
2977
563
{
2978
563
    H5S_sel_iter_t *iter      = NULL;  /* Selection iterator */
2979
563
    bool            iter_init = false; /* Selection iteration info has been initialized */
2980
563
    size_t          nseq_tmp;
2981
563
    size_t          nelem_tmp;
2982
563
    hsize_t         sel_off;
2983
563
    size_t          sel_len;
2984
563
    herr_t          ret_value = SUCCEED; /* Return value */
2985
2986
563
    FUNC_ENTER_NOAPI(FAIL)
2987
2988
    /* Sanity checks */
2989
563
    assert(space);
2990
2991
    /* Allocate and initialize the iterator */
2992
563
    if (NULL == (iter = H5FL_MALLOC(H5S_sel_iter_t)))
2993
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate iterator");
2994
563
    if (H5S_select_iter_init(iter, space, 1, 0) < 0)
2995
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize memory selection information");
2996
563
    iter_init = true;
2997
2998
    /* Get list of sequences for selection, to check if it is contiguous */
2999
563
    if (H5S_SELECT_ITER_GET_SEQ_LIST(iter, (size_t)1, (size_t)-1, &nseq_tmp, &nelem_tmp, &sel_off, &sel_len) <
3000
563
        0)
3001
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL, "sequence length generation failed");
3002
3003
    /* If the first sequence includes all the elements selected in this piece, it it contiguous */
3004
563
    H5_CHECK_OVERFLOW(space->select.num_elem, hsize_t, size_t);
3005
563
    if (sel_len == (size_t)space->select.num_elem) {
3006
563
        if (is_contig)
3007
563
            *is_contig = true;
3008
563
        if (off)
3009
563
            *off = sel_off;
3010
563
        if (len)
3011
0
            *len = sel_len;
3012
563
    }
3013
0
    else if (is_contig)
3014
0
        *is_contig = false;
3015
3016
563
done:
3017
563
    if (iter_init && H5S_SELECT_ITER_RELEASE(iter) < 0)
3018
0
        HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator");
3019
563
    if (iter)
3020
563
        iter = H5FL_FREE(H5S_sel_iter_t, iter);
3021
3022
563
    FUNC_LEAVE_NOAPI(ret_value)
3023
563
} /* end H5S_select_contig_block() */
3024
3025
/*--------------------------------------------------------------------------
3026
 NAME
3027
    H5Ssel_iter_reset
3028
 PURPOSE
3029
    Resets a dataspace selection iterator back to an initial state.
3030
 USAGE
3031
    herr_t H5Ssel_iter_reset(sel_iter_id,space_id)
3032
        hid_t   sel_iter_id;  IN: ID of the dataspace selection iterator to
3033
                                  reset
3034
        hid_t   space_id;     IN: ID of the dataspace with selection to
3035
                                  iterate over
3036
 RETURNS
3037
    Non-negative on success / Negative on failure
3038
 DESCRIPTION
3039
    Resets a dataspace selection iterator back to an initial state so that
3040
    the iterator may be used for iteration once again.
3041
 GLOBAL VARIABLES
3042
 COMMENTS, BUGS, ASSUMPTIONS
3043
 EXAMPLES
3044
 REVISION LOG
3045
--------------------------------------------------------------------------*/
3046
herr_t
3047
H5Ssel_iter_reset(hid_t sel_iter_id, hid_t space_id)
3048
0
{
3049
0
    H5S_sel_iter_t *sel_iter;
3050
0
    H5S_t          *space;
3051
0
    herr_t          ret_value = SUCCEED;
3052
3053
0
    FUNC_ENTER_API(FAIL)
3054
3055
    /* Check args */
3056
0
    if (NULL == (sel_iter = (H5S_sel_iter_t *)H5I_object_verify(sel_iter_id, H5I_SPACE_SEL_ITER)))
3057
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace selection iterator");
3058
0
    if (NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
3059
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace");
3060
3061
    /* Call selection type-specific release routine */
3062
0
    if (H5S_SELECT_ITER_RELEASE(sel_iter) < 0)
3063
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL,
3064
0
                    "problem releasing a selection iterator's type-specific info");
3065
3066
    /* Simply re-initialize iterator */
3067
0
    if (H5S_select_iter_init(sel_iter, space, sel_iter->elmt_size, sel_iter->flags) < 0)
3068
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to re-initialize selection iterator");
3069
3070
0
done:
3071
0
    FUNC_LEAVE_API(ret_value)
3072
0
} /* end H5Ssel_iter_reset() */
3073
3074
/*-------------------------------------------------------------------------
3075
 * Function:  H5S__sel_iter_close_cb
3076
 *
3077
 * Purpose:     Called when the ref count reaches zero on a selection iterator's ID
3078
 *
3079
 * Return:  Non-negative on success / Negative on failure
3080
 *
3081
 *-------------------------------------------------------------------------
3082
 */
3083
herr_t
3084
H5S__sel_iter_close_cb(void *_sel_iter, void H5_ATTR_UNUSED **request)
3085
0
{
3086
0
    H5S_sel_iter_t *sel_iter  = (H5S_sel_iter_t *)_sel_iter; /* The selection iterator to close */
3087
0
    herr_t          ret_value = SUCCEED;                     /* Return value */
3088
3089
0
    FUNC_ENTER_PACKAGE
3090
3091
    /* Sanity check */
3092
0
    assert(sel_iter);
3093
3094
    /* Close the selection iterator object */
3095
0
    if (H5S_sel_iter_close(sel_iter) < 0)
3096
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CLOSEERROR, FAIL, "unable to close selection iterator");
3097
3098
0
done:
3099
0
    FUNC_LEAVE_NOAPI(ret_value)
3100
0
} /* end H5S__sel_iter_close_cb() */
3101
3102
/*-------------------------------------------------------------------------
3103
 * Function:  H5S_sel_iter_close
3104
 *
3105
 * Purpose: Releases a dataspace selection iterator and its memory.
3106
 *
3107
 * Return:  Non-negative on success / Negative on failure
3108
 *
3109
 *-------------------------------------------------------------------------
3110
 */
3111
herr_t
3112
H5S_sel_iter_close(H5S_sel_iter_t *sel_iter)
3113
0
{
3114
0
    herr_t ret_value = SUCCEED; /* Return value */
3115
3116
0
    FUNC_ENTER_NOAPI(FAIL)
3117
3118
    /* Sanity check */
3119
0
    assert(sel_iter);
3120
3121
    /* Call selection type-specific release routine */
3122
0
    if (H5S_SELECT_ITER_RELEASE(sel_iter) < 0)
3123
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL,
3124
0
                    "problem releasing a selection iterator's type-specific info");
3125
3126
    /* Release the structure */
3127
0
    sel_iter = H5FL_FREE(H5S_sel_iter_t, sel_iter);
3128
3129
0
done:
3130
0
    FUNC_LEAVE_NOAPI(ret_value)
3131
0
} /* end H5S_sel_iter_close() */
3132
3133
/*--------------------------------------------------------------------------
3134
 NAME
3135
    H5Ssel_iter_close
3136
 PURPOSE
3137
    Close a dataspace selection iterator
3138
 USAGE
3139
    herr_t H5Ssel_iter_close(sel_iter_id)
3140
        hid_t   sel_iter_id;  IN: ID of the dataspace selection iterator to close
3141
 RETURNS
3142
    Non-negative on success / Negative on failure
3143
 DESCRIPTION
3144
    Close a dataspace selection iterator, releasing its state.
3145
 PROGRAMMER
3146
 GLOBAL VARIABLES
3147
 COMMENTS, BUGS, ASSUMPTIONS
3148
 EXAMPLES
3149
 REVISION LOG
3150
--------------------------------------------------------------------------*/
3151
herr_t
3152
H5Ssel_iter_close(hid_t sel_iter_id)
3153
0
{
3154
0
    herr_t ret_value = SUCCEED; /* Return value */
3155
3156
0
    FUNC_ENTER_API(FAIL)
3157
3158
    /* Check args */
3159
0
    if (NULL == H5I_object_verify(sel_iter_id, H5I_SPACE_SEL_ITER))
3160
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace selection iterator");
3161
3162
    /* When the reference count reaches zero the resources are freed */
3163
0
    if (H5I_dec_app_ref(sel_iter_id) < 0)
3164
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "problem freeing dataspace selection iterator ID");
3165
3166
0
done:
3167
    FUNC_LEAVE_API(ret_value)
3168
0
} /* end H5Ssel_iter_close() */