/*
 * This example shows how to create an unlimited dataset with a 
 * compound data type and write slabs to it.
*/

#include "hdf5.h"

#define FILE          "cuslab.h5"
#define DATASETNAME   "ArrayOfStructures"
#define LENGTH        5 
#define RANK          1

int
main(void)
{

    /* First structure  and dataset*/
    typedef struct s1_t {
	int    a;
	float  b;
	double c; 
    } s1_t;
    s1_t       s1[LENGTH];
    hid_t      s1_tid;     /* File datatype identifier */

    hssize_t offset[1]={0};
    hsize_t count[1]={LENGTH};

    int        i,j;
    hid_t      file, dataset, memspace, space; /* Handles */
    herr_t     status;
    hsize_t    dim[1] = {LENGTH};   /* Dataspace dimensions */
    hsize_t    maxdim[1] = {H5S_UNLIMITED};   /* Dataspace dimensions */
    hid_t      cparms;
    hsize_t    chkdim[1]={3};
    hsize_t    newsize[1]={LENGTH};


    /* Create the data space  */
    space = H5Screate_simple (RANK, dim, maxdim);

    /* Create the file  */
    file = H5Fcreate(FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
    printf ("H5Fcreate: %i\n", file);

    cparms = H5Pcreate (H5P_DATASET_CREATE);
    printf ("H5Pcreate: %i\n", cparms);
    status = H5Pset_chunk ( cparms, RANK, chkdim);
    printf ("H5Pset_chunk: %i\n", status);

    /* Create the memory data type */
    s1_tid = H5Tcreate (H5T_COMPOUND, sizeof(s1_t));
    H5Tinsert(s1_tid, "a_name", HOFFSET(s1_t, a), H5T_NATIVE_INT);
    H5Tinsert(s1_tid, "c_name", HOFFSET(s1_t, c), H5T_NATIVE_DOUBLE);
    H5Tinsert(s1_tid, "b_name", HOFFSET(s1_t, b), H5T_NATIVE_FLOAT);

    /* Create the dataset  */
    dataset = H5Dcreate(file, DATASETNAME, s1_tid, space, cparms);
    printf ("H5Dcreate: %i\n", dataset);

    /* Create memory space for slab writes */
    memspace = H5Dget_space (dataset);
    printf ("H5Dget_space: %i\n", memspace);

    /* Write initial 5 values to dataset */
    for (i = 0; i< LENGTH; i++) {
        s1[i].a = 1;
        s1[i].b = 1;
        s1[i].c = 1;
    }
    status = H5Dwrite(dataset, s1_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, s1);
    printf ("H5Dwrite: %i\n", status);

    /* Loop through, extending dataset by 5 and writing values to just
       the extended portion of dataset */
    for (j=0;j<5;j++)
    {
       for (i = 0; i< LENGTH; i++) {
           s1[i].a = 5+j;
           s1[i].b = 5+j;
           s1[i].c = 5+j;
       }
     
       offset[0] = newsize[0]; 
       newsize[0]=newsize[0]+LENGTH;
       
       status = H5Dextend (dataset, newsize);
       printf ("H5Dextend: %i\n", status);

       space = H5Dget_space (dataset);
       printf ("H5Dget_space: %i\n", space);

       status = H5Sselect_hyperslab (space, H5S_SELECT_SET, offset, NULL,
                count, NULL);
       printf ("H5Sselect_hyperslab: %i\n", status);

       /* Write data to the dataset */
       status = H5Dwrite(dataset, s1_tid, memspace, space, H5P_DEFAULT, s1);
       printf ("H5Dwrite: %i\n", status);

       /* Be sure to close the dataspace IN the loop to avoid using up lots of memory */
       status=H5Sclose(space);
       printf ("H5Sclose: %i\n", status);
       
    }

    /* Release resources */
    status= H5Pclose (cparms);
    printf ("H5Pclose: %i\n", status);
    status= H5Tclose(s1_tid);
    printf ("H5Tclose: %i\n", status);
    status=H5Sclose(memspace);
    printf ("H5Sclose: %i\n", status);
    status=H5Dclose(dataset);
    printf ("H5Dclose: %i\n", status);
    status=H5Fclose(file);
    printf ("H5Fclose: %i\n", status);
}
