/******************************************************************/
/*                                                                */
/*  editcf.c                                                      */
/*                                                                */
/******************************************************************/


#include "hdf5.h"

#define FILE       "cfld.h5"
#define FIELDNAME  "ArrayofStructures"
#define LENGTH     5 
#define ALEN       10
#define RANK       1
#define NMAX       100


typedef struct
{
  int      nsubfields;
  char     *name[NMAX];
  off_t    offset[NMAX];
  hid_t    datatype[NMAX];

} CmpDTSinfo;


int main(void)
{

    herr_t       status = -1;
    
    hid_t        fid, array_dt;
    hid_t        space;
    hid_t        type;
    hid_t        dataset;
    hid_t        s_id;
    
    hsize_t      dim[] = {LENGTH};
    hsize_t      dima[] = {ALEN};

    int          i, j;    
    int          ndims[3] = {1,1,1};
    
    typedef struct
    {
	  int      a[ALEN];
	  float    b[ALEN];
	  double   c[ALEN];
    } CmpField;
    
    CmpField     cf[LENGTH];
    CmpField     cfr[LENGTH];
    CmpDTSinfo   dtsinfo;
    
    typedef struct
    {
      float   b[ALEN];
    } fld_t;
  
    fld_t   fld[LENGTH]; 
    fld_t   fldr[LENGTH]; 
     
    /* Initialize the data */    
    /* ------------------- */
    for (i = 0; i < LENGTH; i++)
	  {        
		for (j = 0; j < ALEN; j++)
		  {
			cf[i].a[j] = 100*(i+1) + j;
			cf[i].b[j] = 100.*(i+1) + 0.01*j;
			cf[i].c[j] = 100.*(i+1) + 0.02*j;
		  }
	  }

	    
    /* Set the number of data members */
    /* ------------------------------ */
    dtsinfo.nsubfields = 3;

    /* Initialize the offsets  */
    /* ----------------------- */
    dtsinfo.offset[0]   = HOFFSET(CmpField, a);
    dtsinfo.offset[1]   = HOFFSET(CmpField, b);
    dtsinfo.offset[2]   = HOFFSET(CmpField, c);

    /* Initialize the data type IDs */
    /* ---------------------------- */    
    dtsinfo.datatype[0] = H5T_NATIVE_INT;
    dtsinfo.datatype[1] = H5T_NATIVE_FLOAT;
    dtsinfo.datatype[2] = H5T_NATIVE_DOUBLE;
       

    /* Initialize the names of data members */
    /* ------------------------------------ */    
    for (i = 0; i < dtsinfo.nsubfields; i++)
      dtsinfo.name[i] = (char *)calloc(20, sizeof(char));	  
	
	strcpy(dtsinfo.name[0], "One");
	strcpy(dtsinfo.name[1], "Two");
	strcpy(dtsinfo.name[2], "Three");
    

    fid = H5Fcreate(FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
    printf("File ID returned by H5Fcreate() :   %d \n", fid);
    

    /* Create data space */
    /* ----------------- */
    space  = H5Screate_simple(RANK, dim, NULL);
    printf("Space ID returned by H5Screate() :   %d \n", space);

    /* Create the memory data type */
    /* --------------------------- */
    type   = H5Tcreate(H5T_COMPOUND, sizeof(CmpField));
    printf("File datatype ID returned by H5Tcreate() :   %d \n", type);

    
    /* Add  members to the compound data type */
    /* -------------------------------------- */
    for ( i = 0; i < dtsinfo.nsubfields; i++)
    {  
        array_dt = H5Tarray_create (dtsinfo.datatype[i], ndims[i], dima, NULL);
        printf ("H5Tarray_create() returns :   %d \n", array_dt); 

        status = H5Tinsert (type, dtsinfo.name[i], dtsinfo.offset[i], array_dt);
        printf("Status returned by H5Tinsert() :   %d \n", status);

        status = H5Tclose(array_dt);
        printf("Status returned by H5Tclose() :   %d \n", status);
    }
	
    /* Create the dataset */
    /* ------------------ */
    dataset = H5Dcreate(fid, FIELDNAME, type, space, H5P_DEFAULT);
    printf("Dataset ID returned by H5Dcreate() :   %d \n", dataset);

    /* Write data to the dataset */
    /* ------------------------- */
    status = H5Dwrite(dataset, type, H5S_ALL, H5S_ALL, H5P_DEFAULT, cf);
    printf("Status returned by H5Dwrite() :   %d \n", status);
    
    status = H5Tclose(type);
    printf ("H5Tclose returns: %d \n", status);
    status = H5Sclose(space);
    printf ("H5Sclose returns: %d \n", status);
    status = H5Dclose(dataset);
    printf ("H5Dclose returns: %d \n", status);
    status = H5Fclose(fid);
    printf ("H5Fclose returns: %d \n", status);
    
/**********************************/
/* Reopen and read entire dataset */
/**********************************/

    fid = H5Fopen(FILE, H5F_ACC_RDWR, H5P_DEFAULT);
    printf ("H5Fopen: %d\n", fid);
    dataset = H5Dopen(fid, FIELDNAME );
    printf ("H5Dopen: %d\n", dataset);
    
    type   = H5Tcreate(H5T_COMPOUND, sizeof(CmpField));
    printf("File datatype ID returned by H5Tcreate() :   %d \n", type);
    for ( i = 0; i < dtsinfo.nsubfields; i++)
    {  
        array_dt = H5Tarray_create (dtsinfo.datatype[i], ndims[i], dima, NULL);
        printf ("H5Tarray_create returns: %d\n", array_dt);
        status = H5Tinsert (type, dtsinfo.name[i], dtsinfo.offset[i], array_dt);
        printf ("H5Tinsert returns: %d \n", status);
        status = H5Tclose(array_dt);
        printf ("H5Tclose returns: %d \n", status);
    }
	
    status = H5Dread(dataset, type, H5S_ALL, H5S_ALL, H5P_DEFAULT, cfr);
    printf("Status returned by H5Dread() :   %d \n\n", status);

    for (i=0; i<LENGTH; i++)
    {
      for (j=0; j <ALEN; j++)
         printf ( "%i ", cfr[i].a[j]);
      printf ("\n");
      for (j=0; j <ALEN; j++)
         printf ( "%5.4f ", cfr[i].b[j]);
      printf ("\n");
      for (j=0; j <ALEN; j++)
         printf ( "%lf ", cfr[i].c[j]);
      printf ("\n\n");
    }

    /* Release memory resources */
    /* ------------------------ */
    for (i = 0; i < dtsinfo.nsubfields; i++)
	  free(dtsinfo.name[i]);


    /* Release IDs */
    /* ----------- */
    status = H5Tclose(type);
    printf ("H5Tclose returns: %d \n", status);
    status = H5Dclose(dataset);
    printf ("H5Dclose returns: %d \n", status);
    status = H5Fclose(fid);
    printf ("H5Fclose returns: %d \n", status);

/******************************/
/* Reopen the file and update */
/******************************/

    fid = H5Fopen(FILE, H5F_ACC_RDWR, H5P_DEFAULT);
    printf("File ID returned by H5Fopen() :   %d \n", fid);    

    dataset = H5Dopen(fid, FIELDNAME );
    printf("The Dataset ID returned by H5Dopen() :   %d \n", dataset);    
    
    type = H5Tcreate(H5T_COMPOUND, sizeof(fld_t));
    printf ("H5Tcreate returns: %i\n", type);

    array_dt = H5Tarray_create (H5T_NATIVE_FLOAT, 1, dima, NULL);
	printf ("H5Tarray_create() returns :   %d \n", array_dt); 

    status = H5Tinsert (type, "Two", HOFFSET(fld_t, b), array_dt);
    printf("Status returned by H5Tinsert() :   %d \n", status);

    for (i=0; i< LENGTH; i++)
    for (j = 0; j < ALEN; j++)
    {
      fld[i].b[j] = 1.313;
    }
    status = H5Dwrite (dataset, type, H5S_ALL, H5S_ALL, H5P_DEFAULT, fld);
    printf ("Status returned by H5Dwrite() :   %d \n", status);

    status = H5Dread (dataset, type, H5S_ALL, H5S_ALL, H5P_DEFAULT, fldr);
    printf ("H5Dread returns: %i\n", status);
   
    for (i=0; i< LENGTH; i++)
    {
      for (j = 0; j < ALEN; j++)
        printf ("%5.4f ", fldr[i].b[j]);
      printf ("\n");
    }
    
    status = H5Dclose(dataset);
    printf("Status returned by H5Dclose() :   %d \n", status);

    status = H5Tclose (type);
    printf("Status returned by H5Tclose() :   %d \n", status);  
  
    status = H5Tclose (array_dt);
    printf("Status returned by H5Tclose() :   %d \n", status);  

    status = H5Fclose(fid);
    printf("Status returned by H5Fclose() :   %d \n", status);  

    return(0);
    
}
