/*
*/

#include "hdf5.h"

#define FILE          "cmpcls.h5"
#define DATASETNAME   "Array"
#define LENGTH        8 
#define RANK          1 

int
main(void)
{

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

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

    int        i,j;
    hid_t      file, dataset, memspace, space, atype, ctype;
    hid_t      dtype, memb_id, native_type, stid;
    H5T_class_t  memb_cls, class;
    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};
    char       nm_suf[2], arrname[5];
    char       *base="St";
    int        nmembs;
    htri_t     retval;


    /* 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);

    atype = H5Tcopy (H5T_C_S1);
    size = 5;
    status = H5Tset_size (atype, size);

    ctype = H5Tcopy (H5T_C_S1);
    size = 5;
    status = H5Tset_size (ctype, size);

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

    /* 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);

    for (i = 0; i< LENGTH; i++) {
       strcpy (arrname, base);
       sprintf (nm_suf, "%i",i); 
       strcat (arrname, nm_suf);
       strcpy (s1[i].a, arrname);
       strcpy (s1[i].c, arrname);
       s1[i].a[5]='\0';
       s1[i].b=i;
       s1[i].c[5]='\0';
    }
    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++) {
          strcpy (arrname, base);
          sprintf (nm_suf, "%i",i); 
          strcat (arrname, nm_suf);
          strcpy (s1[i].a, arrname);
          strcpy (s1[i].c, arrname);
          s1[i].a[5]='\0';
          s1[i].c[5]='\0';
          s1[i].b=5+i;
       }
     
       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);
    }

    /* Release resources */
    status= H5Pclose (cparms);
    status= H5Tclose(s1_tid);
    status=H5Sclose(space);
    status=H5Sclose(memspace);
    status=H5Dclose(dataset);
    status=H5Fclose(file);

    /************************************************************

       Re-open file and check for compound datatype and  
       member class type.  A general tool would have to 
       check for every kind of datatype.  (I know there is only 
       one dataset with a compound datatype with one integer field 
       and 2 string fields in my dataset, so that's all I'm 
       checking.)  (See the H5Tget* functions.) 

    *************************************************************/
    
    file = H5Fopen (FILE, H5F_ACC_RDWR, H5P_DEFAULT);
    dataset = H5Dopen (file, DATASETNAME);
    dtype = H5Dget_type(dataset);
    class = H5Tget_class (dtype);
    native_type=H5Tget_native_type(dtype, H5T_DIR_DEFAULT);

    if (class == H5T_COMPOUND)
    {
       printf ("Dataset Class - H5T_COMPOUND:\n");

       nmembs = H5Tget_nmembers(native_type);

       for (i=0; i < nmembs ; i++)
       {
          memb_id = H5Tget_member_type (native_type, i);
          if (H5Tequal (memb_id, H5T_STD_I32LE))
               printf ("  Member %i:  Type is H5T_STD_I32LE\n", i);
          else 
          {
             size = H5Tget_size (memb_id);
             stid = H5Tcopy (H5T_C_S1);
             status = H5Tset_size (stid, size);
             if (H5Tequal (memb_id, stid))
               printf ("  Member %i:  Type is a string of size %i\n", i, size);
             status = H5Tclose (stid);
          }

          memb_cls = H5Tget_member_class (native_type, i);

          if (memb_cls == H5T_INTEGER)
              printf ("             Class is Integer\n", i);
          else
              if (memb_cls == H5T_STRING)
                 printf ("             Class is String\n", i);
          status = H5Tclose(memb_id);
       }
   }
  
   status = H5Tclose (native_type);
   status = H5Tclose (dtype);
   status = H5Dclose (dataset);
   status = H5Fclose (file);
    
}
