#include "hdf5.h"
#define NFILE "nestc.h5"
#define DIM0 2 
#define DIM1 2 
#define DSET_COMPOUND_NAME    "Nested_Compound"

main () 
{
    typedef struct {
        char            c;
        int             a[5];
        long long       l;
    } s1;
    hid_t         dataset, space, file;
    hid_t         dtype, native_type, tid, tid1, tid2;
    hid_t         tid_m, tid_m1,tid_m2; 
    hid_t         mem_id, nest_mem_id;
    hsize_t       array_dims[1]={5};
    int           i, j, k, n;
    hsize_t       dims[2];
    s1            *temp_point, *temp_chk;
    s1            *points=NULL, *check=NULL;
    void          *tmp;
    herr_t        status;
    

    /* Allocate space for the points & check arrays */
    if((points = malloc(sizeof(s1)*DIM0*DIM1))==NULL)
        printf ("error\n");

    /* Initialize the dataset */
    for (i = n = 0, temp_point=points; i < DIM0; i++) {
      for (j = 0; j < DIM1; j++,temp_point++) {
        temp_point->c = 't'+i+j;
        temp_point->l = (i+j+1);
        for (k = 0; k < 5; k++)
           (temp_point->a)[k] = n++;
      }
    }

    if ((file=H5Fcreate(NFILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT))<0)
       printf ("H5Fcreate failed\n");

    /* Create the data space */
    dims[0] = DIM0;
    dims[1] = DIM1;
    if ((space = H5Screate_simple(2, dims, NULL))<0) 
        printf ("error\n");
        
    /* Create array datatype */
    if((tid2=H5Tarray_create(H5T_STD_I32LE, 1, array_dims, NULL))<0) 
        printf ("error\n");
        
    /* Create compound datatype for disk storage */
    if((tid=H5Tcreate(H5T_COMPOUND, 29))<0) 
        printf ("error\n");
    if((tid1=H5Tcreate(H5T_COMPOUND, 29))<0) 
        printf ("error\n");


    /* Insert members */
    if(H5Tinsert(tid, "c", 0, H5T_C_S1)<0) 
        printf ("error\n");
    if(H5Tinsert(tid, "a", 1, tid2)<0) 
        printf ("error\n");
    if(H5Tinsert(tid, "l", 21, H5T_STD_I64BE)<0)
        printf ("error\n");
    if(H5Tinsert(tid1, "cp", 0, tid) < 0)
        printf ("error\n");

    
    /* Create the dataset */
    if ((dataset = H5Dcreate(file, DSET_COMPOUND_NAME, tid1, 
                   space, H5P_DEFAULT))<0) 
        printf ("error\n");

    /* Create array datatype */
    if((tid_m2=H5Tarray_create(H5T_NATIVE_INT, 1, array_dims, NULL))<0) 
        printf ("error\n");
        
    /* Create compound datatype for datatype in memory */
    if((tid_m=H5Tcreate(H5T_COMPOUND, sizeof(s1)))<0) 
        printf ("error\n");
    if((tid_m1=H5Tcreate(H5T_COMPOUND, sizeof(s1)))<0) 
        printf ("error\n");

    if(H5Tinsert(tid_m, "c", HOFFSET(s1, c), H5T_C_S1)<0) 
        printf ("error\n");
    if(H5Tinsert(tid_m, "a", HOFFSET(s1, a), tid_m2)<0) 
        printf ("error\n");
    if(H5Tinsert(tid_m, "l", HOFFSET(s1, l), H5T_NATIVE_LLONG)<0) 
        printf ("error\n");
    if (H5Tinsert(tid_m1,"cp", 0, tid_m)<0) 
        printf ("error\n");

    /* Write the data to the dataset */
    if (H5Dwrite(dataset, tid_m1, H5S_ALL, H5S_ALL, H5P_DEFAULT, points)<0)
        printf ("error\n");

    /* Close dataset */
    if(H5Dclose(dataset)<0) 
        printf ("error\n");

    /* Close datatype */
    if(H5Tclose(tid)<0) 
        printf ("error\n");
    if(H5Tclose(tid2)<0) 
        printf ("error\n");
    if (H5Tclose (tid1)<0)
        printf ("error\n");
    H5Tclose (tid_m1);

    /* Close dataspace */
    if(H5Sclose(space)<0) 
        printf ("error\n");

    
    if((dataset=H5Dopen(file, DSET_COMPOUND_NAME))<0) 
        printf ("error\n");

    if((dtype=H5Dget_type(dataset))<0) 
        printf ("error\n");

    if((native_type=H5Tget_native_type(dtype, H5T_DIR_DEFAULT))<0)
        printf ("error\n");
    
    if (H5Dread(dataset, native_type, H5S_ALL, H5S_ALL, H5P_DEFAULT, temp_chk)<0)
        printf ("error\n");
    
    check = temp_chk;
    for (i=0; i<4; check++, i++) {
        printf (":\n  %c\n ", check->c);
        for (j=0; j<5; j++)
           printf (" %i", check->a[j]);
        printf ("\n  %lli\n", check->l);
    }

    status = H5Dclose(dataset);
    status = H5Tclose(dtype);
    status = H5Tclose(native_type);
    status = H5Tclose(tid_m);
    status = H5Tclose(tid_m2);
    status = H5Fclose (file);

}


