/*  
 *  This example illustrates different ways of using dataspace
 *  selections in memory and in file.
 */
 
#include "hdf5.h"

#define H5FILE_NAME "SDS_selections.h5"
#define DATASETNAME1 "ALL-ALL" 
#define DATASETNAME2 "ID-ID" 
#define DATASETNAME3 "ID-ALL" 
#define DATASETNAME4 "ALL-ID"
#define NX          5                      /* dataset dimensions */
#define NY          6
#define RANK        2
#define NX_mem1     30                      /* dataset dimensions */
#define NX_mem2     60                      /* dataset dimensions */
#define RANK_mem    1 

int
main (void)
{
    hid_t       file;               /* file and dataset handles */
    hid_t       dataset1, dataset2, dataset3, dataset4; 
    hid_t       space_m, space_f;   /* memory and file dataspace handles */
    hid_t       plist;              /* dataset creation property */
    hsize_t     dims[2];            /* dataset dimensions */
    hsize_t     dims_mem[1];        /* dataset dimensions */
    hssize_t    start[] = {0, 0};
    hsize_t     stride[2];
    hsize_t     count[2];
    hsize_t     block[] = {1,1};
    herr_t      status;                             
    int         buf[NX*NY];         /* data to write */
    int         buf_1[NX_mem1];    
    int         buf_2[NX_mem2];   
    int         i, j;
    int         fill_value = -1;

    /* 
     * Data  initialization. 
     */
    for (j = 0; j < NX*NY;   j++) buf[j]   = j;
    for (j = 0; j < NX_mem1; j++) buf_1[j] = j;
    for (j = 0; j < NX_mem2; j++) buf_2[j] = j;
         
    /*
     * Create a new file using H5F_ACC_TRUNC access,
     * default file creation properties, and default file
     * access properties.
     */
    file = H5Fcreate(H5FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);

    /*
     * Describe the size of the array and create the data space for fixed
     * size dataset. 
     */
    dims[0] = NX;
    dims[1] = NY;
    space_f  = H5Screate_simple(RANK, dims, NULL); 

    /*
     * Set fillvalue to -1
     */
    plist = H5Pcreate(H5P_DATASET_CREATE);
    H5Pset_fill_value(plist, H5T_NATIVE_INT, &fill_value);

    /*
     * Create four datasets within the file using defined dataspace 
     * and dataset creation properties.
     */
    dataset1 = H5Dcreate(file, DATASETNAME1, H5T_NATIVE_INT, space_f, plist);
    dataset2 = H5Dcreate(file, DATASETNAME2, H5T_NATIVE_INT, space_f, plist);
    dataset3 = H5Dcreate(file, DATASETNAME3, H5T_NATIVE_INT, space_f, plist);
    dataset4 = H5Dcreate(file, DATASETNAME4, H5T_NATIVE_INT, space_f, plist);

    /*
     * Write the data from buf to dataset; the result is 
     *
     *       0  1  2  3  4  5  
     *       6  7  8  9 10 11 
     *      12 13 14 15 16 17
     *      18 19 20 21 22 23
     *      24 25 26 27 28 29
     */
     
    status = H5Dwrite(dataset1, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
		      H5P_DEFAULT, buf);

    /*
     * Now select each forth element from the memory buffer buf_2 and
     * write it to the every second element in the dataset.
     */

    /*   
     * Memory selection from one dimensional space
     */
    dims_mem[0] = NX_mem2;
    space_m  = H5Screate_simple(RANK_mem, dims_mem, NULL); 
    stride[0] = 4;
    count[0]  = 15;
    H5Sselect_hyperslab(space_m, H5S_SELECT_SET,start, stride, count, block);
    
    /*
     * File dataspace selection of each second element
     */
    stride[0] = 1;
    stride[1] = 2;
    count[0]  = 5;
    count[1]  = 3;
    H5Sselect_hyperslab(space_f, H5S_SELECT_SET,start, stride, count, block);
    
    /*
     * Write a dataset, the result is
     *
     *       0  -1   4  -1   8  -1
     *      12  -1  16  -1  20  -1
     *      24  -1  28  -1  32  -1
     *      36  -1  40  -1  44  -1
     *      48  -1  52  -1  56  -1
     */  
    status = H5Dwrite(dataset2, H5T_NATIVE_INT, space_m, space_f,
		      H5P_DEFAULT, buf_2);

    /*
     * Now select each second element from the memory buffer buf_1 and
     * write it to the whole dataset.
     */

    /*   
     * Memory selection from one dimensional space
     */
    dims_mem[0] = NX_mem2;
    space_m  = H5Screate_simple(RANK_mem, dims_mem, NULL); 
    stride[0] = 2;
    count[0]  = 30;
    H5Sselect_hyperslab(space_m, H5S_SELECT_SET,start, stride, count, block);
    
    /*
     * Write a dataset, the result is
     *
     *       0   2   4   6   8  10
     *      12  14  16  18  20  22 
     *      24  26  28  30  32  34 
     *      36  38  40  42  44  46 
     *      48  50  52  52  56  58 
     */  
    status = H5Dwrite(dataset3, H5T_NATIVE_INT, space_m, H5S_ALL,
		      H5P_DEFAULT, buf_2);

    /*
     * Now select each second element from the file  and
     * write each second element from the buffer buf_1 to it.
     */

    /*
     * File dataspace selection of each second element
     */
    stride[0] = 1;
    stride[1] = 2;
    count[0]  = 5;
    count[1]  = 3;
    H5Sselect_hyperslab(space_f, H5S_SELECT_SET,start, stride, count, block);

    /*
     * Write the data to the dataset; the result is 
     *
     *       0  -1   2  -1   4  -1   
     *       6  -1   8  -1  10  -1
     *      12  -1  14  -1  16  -1
     *      18  -1  20  -1  22  -1
     *      24  -1  26  -1  28  -1
     */
    status = H5Dwrite(dataset4, H5T_NATIVE_INT, H5S_ALL, space_f,
		      H5P_DEFAULT, buf_1);

    /*
     * Close/release resources.
     */
    H5Sclose(space_m);
    H5Sclose(space_f);
    H5Dclose(dataset1);
    H5Dclose(dataset2);
    H5Dclose(dataset3);
    H5Dclose(dataset4);
    H5Fclose(file);
 
    return 0;
}     
