/*

*/

#include "hdf5.h"

#define filename "ref.h5"
#define dsetnamev "MATRIX"
#define dsetnamer "REGION_REFERENCES"

int main()
{
    hid_t file_id;        /* file identifier */
    hid_t space_id;       /* dataspace identifiers */
    hid_t spacer_id;      
    hid_t dsetv_id;       /*dataset identifiers*/
    hid_t dsetr_id;      
    hsize_t dims[2] =  {2,9};
    hsize_t dimsr[1] =  {2};
    int rank = 2;
    int rankr =1;
    herr_t status;
    hdset_reg_ref_t ref[2];
    hdset_reg_ref_t ref_out[2];
    int data[2][9] = {1,1,2,3,3,4,5,5,6,1,2,2,3,4,4,5,6,6};
    int data_out[2][9] = {0};
    hsize_t start[2];
    hsize_t count[2];
    hsize_t coord[2][3] = {0, 0, 1, 6, 0, 8};
    int num_points = 3;
    int i, j;
    H5G_stat_t statbuf;

/*******************************************************/
/* Create a file with a dataset with region references */
/*******************************************************/

    file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);

    space_id = H5Screate_simple(rank, dims, NULL);
    spacer_id = H5Screate_simple(rankr, dimsr, NULL);

    dsetv_id = H5Dcreate(file_id, dsetnamev, H5T_NATIVE_INT, space_id, H5P_DEFAULT);

    status = H5Dwrite(dsetv_id, H5T_NATIVE_INT, H5S_ALL , H5S_ALL, H5P_DEFAULT,data);

    dsetr_id = H5Dcreate(file_id, dsetnamer, H5T_STD_REF_DSETREG, spacer_id, H5P_DEFAULT);

    start[0] = 0; 
    start[1] = 3; 
    count[0] = 2;
    count[1] = 3;
    status = H5Sselect_hyperslab(space_id,H5S_SELECT_SET,start,NULL,count,NULL);
    status = H5Rcreate(&ref[0], file_id, dsetnamev, H5R_DATASET_REGION, space_id);

    status = H5Sselect_none(space_id);
    status = H5Sselect_elements(space_id, H5S_SELECT_SET,num_points,
                                (const hsize_t **)coord);
    status = H5Rcreate(&ref[1], file_id, dsetnamev, H5R_DATASET_REGION, space_id);

    status = H5Dwrite(dsetr_id, H5T_STD_REF_DSETREG, H5S_ALL, H5S_ALL, H5P_DEFAULT,ref);


    status = H5Sclose(space_id);
    status = H5Sclose(spacer_id);
    status = H5Dclose(dsetr_id);
    status = H5Dclose(dsetv_id);
    status = H5Fclose(file_id);

/*****************************************/
/* Re-open file and read selections back */
/*****************************************/

    file_id = H5Fopen(filename, H5F_ACC_RDWR,  H5P_DEFAULT);

  /* Open References Dataset */
    dsetr_id = H5Dopen (file_id, dsetnamer);

  /* Get information about a specific dataset, by passing in
   * the name of the Dataset */

    printf ("\nH5Gget_objinfo for Dataset %s:\n", dsetnamev); 
    status = H5Gget_objinfo (file_id, dsetnamev, NULL, &statbuf);
    printf ("  statbuf: %lli %lli %lli %lli\n ",statbuf.fileno[0], 
              statbuf.fileno[1], statbuf.objno[0], statbuf.objno[1]);

    status = H5Dread(dsetr_id, H5T_STD_REF_DSETREG, H5S_ALL, H5S_ALL, 
                   H5P_DEFAULT, ref_out);

  /* Dereference the first reference.  */
    dsetv_id = H5Rdereference(dsetr_id, H5R_DATASET_REGION, &ref_out[0]);
    space_id = H5Rget_region(dsetr_id, H5R_DATASET_REGION,&ref_out[0]);

  /* Get information about the dataset pointed to by the 
   * dereferenced object. */
 
    printf ("\nH5Gget_objinfo for Dereferenced Dataset:\n"); 
    status = H5Gget_objinfo (dsetv_id, ".", NULL, &statbuf);
    printf ("  statbuf: %lli %lli %lli %lli\n ",statbuf.fileno[0], 
            statbuf.fileno[1], statbuf.objno[0], statbuf.objno[1]);



  /* Read and display hyperslab selection from the dataset.  */

    status = H5Dread(dsetv_id, H5T_NATIVE_INT, H5S_ALL, space_id, 
                   H5P_DEFAULT, data_out);
    printf("\nSelected hyperslab: ");
    for (i = 0; i <= 1; i++)
    {   
        printf("\n");
        for (j = 0; j <= 8; j++)
            printf("%d ", data_out[i][j]);
    }
    printf("\n");

    status = H5Sclose(space_id);
    status = H5Dclose(dsetv_id);

    for (i = 0; i <= 1; i++)
        for (j = 0; j <= 8; j++)
            data_out[i][j] = 0;

  /* Dereference the second reference.  */

    dsetv_id = H5Rdereference(dsetr_id, H5R_DATASET_REGION, &ref_out[1]);
    space_id = H5Rget_region(dsetv_id, H5R_DATASET_REGION,&ref_out[1]);

  /* Get information about the dataset pointed to by the 
   * dereferenced object. */
 
    printf ("\nH5Gget_objinfo for Dereferenced Dataset:\n"); 
    status = H5Gget_objinfo (dsetv_id, ".", NULL, &statbuf);
    printf ("  statbuf: %lli %lli %lli %lli\n ",statbuf.fileno[0], statbuf.fileno[1], statbuf.objno[0], statbuf.objno[1]);


  /* Read selected data from the dataset.  */

    status = H5Dread(dsetv_id, H5T_NATIVE_INT, H5S_ALL, space_id, 
                   H5P_DEFAULT, data_out);
    printf("\nSelected points: ");
    for (i = 0; i <= 1; i++)
    {   
        printf("\n");
        for (j = 0; j <= 8; j++)
            printf("%d ", data_out[i][j]);
    }
    printf("\n");

  /* Close dataspace and the dataset.  */

    status = H5Sclose(space_id);
    status = H5Dclose(dsetr_id);
    status = H5Dclose(dsetv_id);
    status = H5Fclose(file_id);

    return 0;
}
    

