/** \defgroup H5LR Extensions
 *
 * <em>Working with region references, hyperslab selections,
 * and bit-fields (H5LR, H5LT)</em>
 *
 * The following reference manual entries describe high-level HDF5 C and Fortran APIs
 * for working with region references, hyperslab selections, and bit-fields.
 * These functions were created as part of a project supporting
 * NPP/NPOESS Data Production and Exploitation (
 * <a href="https://support.hdfgroup.org/projects/jpss/documentation">
 * project</a>, <a href="https://gamma.hdfgroup.org/ftp/pub/outgoing/NPOESS/source">
 * software </a>).
 * While they were written to facilitate access to NPP, NPOESS, and JPSS
 * data in the HDF5 format, these functions may be useful to anyone working
 * with region references, hyperslab selections, or bit-fields.
 *
 * Note that these functions are not part of the standard HDF5 distribution; 
 * the <a href="https://gamma.hdfgroup.org/ftp/pub/outgoing/NPOESS/source">
 * software </a>
 * must be separately downloaded and installed.
 *
 * A comprehensive guide to this library,
 * <a href="https://support.hdfgroup.org/projects/jpss/documentation/HL/UG/NPOESS_HL-UG.pdf">
 * <em>User Guide to the HDF5 High-level Library for Handling Region References and Hyperslab Selections</em></a>
 * is available at
 * https://support.hdfgroup.org/projects/jpss/documentation/HL/UG/NPOESS_HL-UG.pdf.
 *
 * - \ref H5LRcopy_reference
 *        \n Copies data from the specified dataset to a new location and creates a reference to it.
 * - \ref H5LRcopy_region
 *        \n  Copies data from a referenced region to a region in a destination dataset.
 * - \ref H5LRcreate_ref_to_all
 *        \n  Creates a dataset with the region references to the data in all datasets located under a
 *        specified group in a file or creates a dataset with object references to all objects (groups or datasets)
 *        located under a specified group in a file.
 * - \ref H5LRcreate_region_references
 *        \n Creates an array of region references using an array of paths to
 *        datasets and an array of corresponding hyperslab descriptions.
 * - \ref H5LRget_region_info
 *        \n Retrieves information about the data a region reference points to.
 * - \ref H5LRmake_dataset
 *        \n Creates and writes a dataset containing a list of region references.
 * - \ref H5LRread_region
 *        \n  Retrieves raw data pointed to by a region reference to an application buffer.
 * - \ref H5LTcopy_region
 *        \n Copies data from a specified region in a source dataset to a specified region in a destination dataset.
 * - \ref H5LTread_bitfield_value
 *        \n Retrieves the values of quality flags for each element to the application provided buffer.
 * - \ref H5LTread_region
 *        \n Reads selected data to an application buffer.
 *
 */

/*-------------------------------------------------------------------------
 *
 * Make dataset functions
 *
 *-------------------------------------------------------------------------
 */

/**
 * --------------------------------------------------------------------------
 * \ingroup H5LR
 *
 * \brief Creates and writes a dataset containing a list of region references.
 *
 * \fgdta_loc_id
 * \param[in] path          Path to the dataset being created
 * \param[in] type_id       Datatype of the dataset
 * \param[in] buf_size      Size of the \p loc_id_ref and \p buf arrays
 * \param[in] loc_id_ref    Array of object identifiers; each identifier
 *                          describes to which HDF5 file the corresponding
 *                          region reference belongs to
 * \param[in] buf           Array of region references
 *
 * \return \herr_t
 *
 * \details Given an array of size \p buf_size of region references \p buf,
 *          the function will create a dataset with path \p path, at location
 *          specified by \p loc_id and of a datatype specified by \p type_id,
 *          and will write data associated with each region reference in the order
 *          corresponding to the order of the region references in the buffer.
 *          It is assumed that all referenced hyperslabs have the same dimensionality,
 *          and only the size of the slowest changing dimension may differ.
 *          Each reference in the \p buf array belongs to the file identified
 *          by the corresponding object identifiers in the array \p loc_id_ref.
 *
 *          If \p path does not exist in \p loc_id then the function will
 *          create the path specified by \p path automatically.
 *
 * \version 1.1 Fortran wrapper introduced in this release.
 *
 * \since 1.0
 *
 */
H5_HLRDLL herr_t H5LRmake_dataset(hid_t loc_id,
                 const char *path,
                 hid_t type_id, const size_t buf_size,
                 const hid_t *loc_id_ref,
                 const hdset_reg_ref_t *buf);

/*-------------------------------------------------------------------------
 *
 * Make and manipulate dataset region references functions
 *
 *-------------------------------------------------------------------------
 */

/**
 * --------------------------------------------------------------------------
 * \ingroup H5LR
 *
 * \brief Creates an array of region references using an array of paths to
 *        datasets and an array of corresponding hyperslab descriptions.
 *
 * \param[in] obj_id        File identifier for the HDF5 file containing
 *                          the referenced regions or an object identifier
 *                          for any object in that file
 * \param[in] num_elem      Number of elements in the \p path and \p buf arrays
 * \param[in] path          Array of pointers to strings, which contain
 *                          the paths to the target datasets for the region references
 * \param[in] block_coord   Array of hyperslab coordinate
 * \param[out] buf          Buffer for returning an array of region references
 *
 * \return \herr_t
 *
 * \note    **Motivation:**
 * \note    H5LRcreate_region_references() is useful when creating
 *          large numbers of similar region references.
 *
 * \details H5LRcreate_region_references() creates a list of region references
 *          given an array of paths to datasets and another array listing the
 *          corner coordinates of the corresponding hyperslabs.
 *
 *          \p path parameter is an array of pointers to strings.
 *
 *          \p num_elem specifies the number of region references to be created,
 *          thus specifying the size of the \p path and \p _buf arrays.
 *
 *          Buffer \p block_coord has size 2*rank and is the coordinates of the
 *          starting point following by the coordinates of the ending point of
 *          the hyperslab, repeated \p num_elem times for each hyperslab.
 *          For example, creating two region references to two hyperslabs,
 *          one with a rectangular hyperslab region starting at element (2,2)
 *          to element (5,4) and the second rectangular region starting at
 *          element (7,7) to element (9,10), results in \p block_coord
 *          being {2,2,5,4, 7,7,9,10}.
 *
 *          The rank of the hyperslab will be the same as the rank of the
 *          target dataset. H5LRcreate_region_references() will retrieve
 *          the rank for each dataset and will use those values to interpret
 *          the values in the buffer. Please note that rank may vary from one
 *          dataset to another.
 *
 * \version 1.1 Fortran wrapper introduced in this release.
 *
 * \since 1.0
 *
 */
H5_HLRDLL herr_t H5LRcreate_region_references(hid_t obj_id,
                      size_t num_elem,
                      const char **path,
                      const hsize_t *block_coord,
                      hdset_reg_ref_t *buf);

/**
 * --------------------------------------------------------------------------
 * \ingroup H5LR
 *
 * \brief Copies data from the specified dataset to a new location and creates a reference to it.
 *
 * \param[in] obj_id        Identifier of any object in a file an HDF5 reference belongs to
 * \param[in] ref           Reference to the datasets region
 * \param[in] file          Name of the destination file
 * \param[in] path          Full path to the destination dataset
 * \param[in] block_coord   Hyperslab coordinates in the destination dataset
 * \param[out] ref_new      Region reference to the new location of data
 *
 * \return \herr_t
 *
 * \details Given a data set pointed to by a region reference, the function
 *          H5LRcopy_reference() will copy the hyperslab data referenced by
 *          a datasets region reference into existing dataset specified by
 *          its path \p path in the file with the name \p file, and to location
 *          specified by the hyperslab coordinates \p block_coord. It will
 *          create the region reference \p ref_new to point to the new location.
 *          The number of elements in the old and newly specified regions has
 *          to be the same.
 *
 *          Buffer \p block_coord has size 2*rank and is the coordinates of
 *          the starting point following by the coordinates of the ending
 *          point of the hyperslab. For example, to extract a rectangular
 *          hyperslab region starting at element (2,2) to element (5,4)
 *          then \p block_coord would be {2, 2, 5, 4}.
 *
 * \version 1.1 Fortran wrapper introduced in this release.
 *
 * \since 1.0
 *
 */
H5_HLRDLL herr_t H5LRcopy_reference(hid_t obj_id, hdset_reg_ref_t *ref, const char *file,
                     const char *path, const hsize_t *block_coord,
                     hdset_reg_ref_t *ref_new);

/**
 * --------------------------------------------------------------------------
 * \ingroup H5LR
 *
 * \brief Copies data from a referenced region to a region in a destination dataset.
 *
 * \param[in] obj_id        Identifier of any object in a file
 *                          dataset region reference belongs to
 * \param[in] ref           Dataset region reference
 * \param[in] file          Name of the destination file
 * \param[in] path          Full path to the destination dataset
 * \param[in] block_coord   Hyperslab coordinates in the destination dataset
 *
 * \return \herr_t
 *
 * \details Given a dataset region reference \p ref in a source file
 *          specified by an identifier of any object in that file
 *          \p obj_id, the function will write data to the existing
 *          dataset \p path in file \p file to the simple hyperslab
 *          specified by \p block_coord.
 *
 *          Buffer \p block_coord has size 2*rank and is the coordinates
 *          of the starting point following by the coordinates of the
 *          ending point of the hyperslab. For example, to specify a
 *          rectangular hyperslab destination region starting at element
 *          (2,2) to element (5,4) then \p block_coord would be {2, 2, 5, 4}.
 *
 *          If \p path does not exist in the destination file (as may be
 *          the case when writing to a new file) then the dataset will be
 *          copied directly to the \p path and \p block_coord will be
 *          disregarded.
 *
 * \version 1.1 Fortran wrapper introduced in this release.
 *
 * \since 1.0
 *
 */
H5_HLRDLL herr_t H5LRcopy_region(hid_t obj_id,
                 hdset_reg_ref_t *ref,
                 const char *file,
                 const char *path,
                 const hsize_t *block_coord);

/**
 * --------------------------------------------------------------------------
 * \ingroup H5LR
 *
 * \brief Creates a dataset with the region references to the data
 *        in all datasets located under a specified group in a file
 *        or creates a dataset with object references to all objects
 *        (groups or datasets) located under a specified group in a file.
 *
 * \fg_loc_id
 * \param[in] group_path    Absolute or relative path to the group at which traversal starts
 * \param[in] ds_path       Absolute or relative path to the dataset with region references to be created
 * \param[in] index_type    Index_type; see valid values below in description
 * \param[in] order         Order in which index is traversed; see valid values below in description
 * \param[in] ref_type      Reference type; see valid values below in description
 *
 * \return \herr_t
 *
 * \details H5LRcreate_ref_to_all() creates a dataset with the
 *          region references to the data in all datasets located
 *          under a specified group in a file or creates a dataset with
 *          object references to all objects (groups or datasets) located
 *          under a specified group in a file.
 *
 *          Given a dataset path \p ds_path in a file specified by the
 *          \p loc_id identifier, the function H5LRcreate_ref_to_all()
 *          will create a contiguous one-dimensional dataset with the
 *          region references or object references depending on the value
 *          of the \p ref_type parameter. When \p ref_type is
 *          #H5R_DATASET_REGION, each region reference points to all data
 *          in a dataset encountered by an internally called H5Lvisit()
 *          routine, which starts at the group specified by the \p loc_id
 *          and \p group_path parameters. In a like manner, when
 *          \p ref_type is #H5R_OBJECT, each object reference points to
 *          an object (a group or a dataset) encountered by H5Lvisit().
 *
 *          If \p ds_path does not exist in \p loc_id then the function
 *          will create the path specified by \p ds_path automatically.
 *
 *          \p index_type specifies the index to be used.
 *          Valid values include the following:
 *          - #H5_INDEX_NAME        Alphanumeric index on name
 *          - #H5_INDEX_CRT_ORDER   Index on creation order
 *
 *          \p order specifies the order in which objects are to be
 *          inspected along the index specified in \p index_type.
 *          Valid values include the following:
 *          - #H5_ITER_INC      Increasing order
 *          - #H5_ITER_DEC      Decreasing order
 *          - #H5_ITER_NATIVE   Fastest available order
 *
 *          For more detailed information on these two parameters,
 *          @see H5Lvisit().
 *
 *          \p ref_type specifies the type of the reference to be used.
 *          Valid values include the following:
 *          - #H5R_DATASET_REGION   Dataset region reference
 *          - #H5R_OBJECT           Object reference
 *
 * \version 1.1 Fortran wrapper introduced in this release.
 *
 * \since 1.0
 *
 */
H5_HLRDLL herr_t H5LRcreate_ref_to_all(hid_t loc_id, const char *group_path,
                  const char *ds_path, H5_index_t index_type, H5_iter_order_t order, H5R_type_t ref_type);

/*-------------------------------------------------------------------------
 *
 * Read dataset functions
 *
 *-------------------------------------------------------------------------
 */

/**
 * --------------------------------------------------------------------------
 * \ingroup H5LR
 *
 * \brief Retrieves raw data pointed to by a region reference 
 *        to an application buffer.
 *
 * \param[in] obj_id        File identifier for the HDF5 file containing
 *                          the dataset with the referenced region or an
 *                          object identifier for any object in that file
 * \param[in] ref           Region reference specifying data to be read in
 * \param[in] mem_type      Memory datatype of data read from referenced
 *                          region into the application buffer
 * \param[in,out] numelem   Number of elements to be read into buffer \p buf
 * \param[out] buf          Buffer in which data is returned to the application
 *
 * \return \herr_t
 *
 * \details H5LRread_region() reads data pointed to by the region
 *          reference \p ref into the buffer \p buf.
 *
 *          \p numelem specifies the number of elements to be read
 *          into \p buf. When the size of the reference region is unknown,
 *          H5LRread_region() can be called with \p buf set to NULL;
 *          the number of elements in the referenced region will be returned
 *          in \p numelem.
 *
 *          The buffer buf must be big enough to hold \p numelem elements
 *          of type \p mem_type. For example, if data is read from the referenced
 *          region into an integer buffer, \p mem_type should be #H5T_NATIVE_INT
 *          and the buffer must be at least \c sizeof(int) * \p numelem  bytes
 *          in size. This buffer must be allocated by the application.
 *
 * \version 1.1 Fortran wrapper introduced in this release.
 *
 * \since 1.0
 *
 */
H5_HLRDLL herr_t H5LRread_region(hid_t obj_id,
                 const hdset_reg_ref_t *ref,
                 hid_t mem_type,
                 size_t *numelem,
                 void *buf );

/*-------------------------------------------------------------------------
 *
 * Query dataset functions
 *
 *-------------------------------------------------------------------------
 */

/**
 * --------------------------------------------------------------------------
 * \ingroup H5LR
 *
 * \brief Retrieves information about the data a region reference points to.
 *
 * \param[in] obj_id        Identifier of any object in an HDF5 file the region reference belongs to.
 * \param[in] ref           Region reference to query
 * \param[in,out] len       Size of the buffer to store \p path in.
 *                          NOTE: if \p *path is not NULL then \p *len must be the appropriate length
 * \param[out] path         Full path that a region reference points to
 * \param[out] rank         The number of dimensions of the dataset
 *                          dimensions of the dataset pointed by region reference.
 * \param[out] dtype        Datatype of the dataset pointed by the region reference.
 * \param[out] sel_type     Type of the selection (point or hyperslab)
 * \param[in,out] numelem   Number of coordinate blocks or selected elements.
 * \param[out] buf          Buffer containing description of the region pointed by region reference
 *
 * \return \herr_t
 *
 * \details H5LRget_region_info() queries information about the data
 *          pointed by a region reference \p ref. It returns one of the
 *          absolute paths to a dataset, length of the path, dataset's rank
 *          and datatype, description of the referenced region and type of
 *          the referenced region. Any output argument can be NULL if that
 *          argument does not need to be returned.
 *
 *          The parameter \p obj_id is an identifier for any object in the
 *          HDF5 file containing the referenced object. For example, it can
 *          be an identifier of a dataset the region reference belongs to
 *          or an identifier of an HDF5 file the dataset with region references
 *          is stored in.
 *
 *          The parameter \p ref is a region reference to query.
 *
 *          The parameter \p path is a pointer to application allocated
 *          buffer of size \p len+1 to return an absolute path to a dataset
 *          the region reference points to.
 *
 *          The parameter \p len is a length of absolute path string plus
 *          the \0 string terminator. If path parameter is NULL, actual
 *          length of the path (+1 for \0 string terminator) is returned to
 *          application and can be used to allocate buffer path of an
 *          appropriate length \p len.
 *
 *          The parameter \p sel_type describes the type of the selected
 *          region. Possible values can be #H5S_SEL_POINTS for point
 *          selection and #H5S_SEL_HYPERSLABS for hyperslab selection.
 *
 *          The parameter \p numelem describes how many elements will be
 *          placed in the buffer \p buf. The number should be interpreted
 *          using the value of \p sel_type.
 *
 *          If value of \p sel_type is #H5S_SEL_HYPERSLABS, the parameter
 *          \p buf contains \p numelem blocks of the coordinates for each
 *          simple hyperslab of the referenced region. Each block has
 *          length \c 2*\p rank and is organized as follows: <"start" coordinate>,
 *          immediately followed by <"opposite" corner coordinate>.
 *          The total size of the buffer to hold the description of the
 *          region will be \c 2*\p rank*\p numelem. If region reference
 *          points to a contiguous sub-array, then the value of \p numelem
 *          is 1 and the block contains coordinates of the upper left and
 *          lower right corners of the sub-array (or simple hyperslab).
 *
 *          If value of \p sel_type is #H5S_SEL_POINTS, the parameter \p buf
 *          contains \p numelem blocks of the coordinates for each selected
 *          point of the referenced region. Each block has length \p rank
 *          and contains coordinates of the element. The total size of the
 *          buffer to hold the description of the region will be
 *          \p rank* \p numelem.
 *
 *
 * \version 1.1 Fortran wrapper introduced in this release.
 *
 * \since 1.0
 *
 */
H5_HLRDLL herr_t H5LRget_region_info(hid_t obj_id,
                     const hdset_reg_ref_t *ref,
                     size_t *len, 
                     char *path,
                     int *rank,
                     hid_t *dtype,
                     H5S_sel_type *sel_type,
                     size_t *numelem,
                     hsize_t *buf );



/*-------------------------------------------------------------------------
 *
 * Make dataset functions
 *
 *-------------------------------------------------------------------------
 */

/**
 * --------------------------------------------------------------------------
 * \ingroup H5LR
 *
 * \brief Copies data from a specified region in a source dataset
 *        to a specified region in a destination dataset
 *
 * \param[in] file_src          Name of the source file
 * \param[in] path_src          Full path to the source dataset
 * \param[in] block_coord_src   Hyperslab coordinates in the source dataset
 * \param[in] file_dest         Name of the destination file
 * \param[in] path_dest         Full path to the destination dataset
 * \param[in] block_coord_dset  Hyperslab coordinates in the destination dataset
 *
 * \return \herr_t
 *
 * \details Given a path to a dataset \p path_src in a file with the
 *          name \p file_src, and description of a simple hyperslab of
 *          the source \p block_coord_src, the function will write data
 *          to the dataset \p path_dest in file \p file_dest to the
 *          simple hyperslab specified by \p block_coord_dset.
 *          The arrays \p block_coord_src and \p block_coord_dset have
 *          a length of 2*rank and are the coordinates of the starting
 *          point following by the coordinates of the ending point of the
 *          hyperslab. For example, to specify a rectangular hyperslab
 *          destination region starting at element (2,2) to element (5,4)
 *          then \p block_coord_dset would be {2, 2, 5, 4}.
 *
 *          If \p path_dest does not exist in the destination file
 *          (as may be the case when writing to a new file) then the
 *          dataset will be copied directly to the \p path_dest and
 *          \p block_coord_dset will be disregarded.
 *
 * \version 1.1 Fortran wrapper introduced in this release.
 *
 * \since 1.0
 *
 */
H5_HLRDLL herr_t H5LTcopy_region(const char *file_src,
                 const char *path_src,
                 const hsize_t *block_coord_src,
                 const char *file_dest,
                 const char *path_dest,
                 const hsize_t *block_coord_dset);

/*-------------------------------------------------------------------------
 *
 * Read dataset functions
 *
 *-------------------------------------------------------------------------
 */

/**
 * --------------------------------------------------------------------------
 * \ingroup H5LR
 *
 * \brief Reads selected data to an application buffer.
 *
 * \param[in] file          Name of file
 * \param[in] path          Full path to a dataset
 * \param[in] block_coord   Hyperslab coordinates
 * \param[in] mem_type      Memory datatype, describing the buffer the referenced data will be read into
 * \param[out] buf          Buffer containing data from the referenced region
 *
 * \return \herr_t
 *
 * \details H5LTread_region() reads data from a region described by
 *          the hyperslab coordinates in \p block_coord, located in
 *          the dataset specified by its absolute path \p path in a
 *          file specified by its name \p file. Data is read into a
 *          buffer \p buf of the datatype that corresponds to the
 *          HDF5 datatype specified by \p mem_type.
 *
 *          Buffer \p block_coord has size 2*rank and is the coordinates
 *          of the starting point following by the coordinates of the
 *          ending point of the hyperslab. For example, to extract a
 *          rectangular hyperslab region starting at element (2,2) to
 *          element (5,4) then \p block_coord would be {2, 2, 5, 4}.
 *
 *          Buffer \p buf should be big enough to hold selected elements
 *          of the type that corresponds to the \p mem_type
 *
 * \version 1.1 Fortran wrapper introduced in this release.
 *
 * \since 1.0
 *
 */
H5_HLRDLL herr_t  H5LTread_region(const char *file,
                  const char *path,
                  const hsize_t *block_coord,
                  hid_t mem_type,
                  void *buf );

/**
 * --------------------------------------------------------------------------
 * \ingroup H5LR
 *
 * \brief Retrieves the values of quality flags for each element
 *        to the application provided buffer.
 *
 * \param[in] dset_id   Identifier of the dataset with bit-field values
 * \param[in] num_values    Number of the values to be extracted
 * \param[in] offset        Array of staring bits to be extracted from
 *                          the element; valid values: 0 (zero) through 7
 * \param[in] lengths       Array of the number of bits to be extracted for each value
 * \param[in] space         Dataspace identifier, describing the elements
 *                          to be read from the dataset with bit-field values
 * \param[out] buf          Buffer to read the values in
 *
 * \return \herr_t
 *
 * \details H5LTread_bitfield_value() reads selected elements from a
 *          dataset specified by its identifier \p dset_id, and unpacks
 *          the bit-field values to a buffer \p buf.
 *
 *          The parameter \p space is a space identifier that indicates
 *          which elements of the dataset should be read.
 *
 *          The parameter \p offset is an array of length \p num_values;
 *          the i<sup>th</sup> element of the array holds the value of the
 *          starting bit of the i<sup>th</sup> bit-field value.
 *          Valid values are: 0 (zero) through 7.
 *
 *          The parameter \p lengths is an array of length \p num_values;
 *          the i<sup>th</sup> element of the array holds the number of
 *          bits to be extracted for the i<sup>th</sup> bit-field value.
 *          Extracted bits will be interpreted as a base-2 integer value.
 *          Each value will be converted to the base-10 integer value and
 *          stored in the application buffer.
 *
 *          Buffer \p buf is allocated by the application and should be big
 *          enough to hold \c num_sel_elem * \p num_values elements of the
 *          specified type, where \c num_sel_elem is a number of the elements
 *          to be read from the dataset. Data in the buffer is organized
 *          as \p num_values values for the first element, followed by the
 *          \p num_values values for the second element, ... , followed by
 *          the \p num_values values for the
 *          \c num_selected_elem<sup>th</sup> element.
 *
 * \version 1.1 Fortran wrapper introduced in this release.
 *
 * \since 1.0
 *
 */
H5_HLRDLL herr_t H5LTread_bitfield_value(hid_t dset_id, int num_values, const unsigned *offset,
                 const unsigned *lengths, hid_t space, int *buf);

