/* 
 *  This program illustrates the usage of the H5A Interface functions.
 *  It creates and writes a dataset, and then creates and writes array,
 *  scalar, and string attributes of the dataset. 
 *  The H5Aiterate function is used to iterate through the dataset attributes,
 *  and display their names and values.
 */ 
 
#include <stdlib.h>

#include "hdf5.h"

#define H5FILE_NAME "Attributes.h5"

#define RANK  1   /* Rank and size of the dataset  */ 
#define SIZE  7

#define ARANK  2   /* Rank and dimension sizes of the first dataset attribute */
#define ADIM1  2
#define ADIM2  3 
#define ANAME  "Float attribute"      /* Name of the array attribute */
#define ANAMES "Character attribute" /* Name of the string attribute */

herr_t attr_info(hid_t loc_id, const char *name, void *opdata); 
                                     /* Operator function */

int 
main (void)
{

   hid_t   file, dataset;       /* File and dataset identifiers */
   
   hid_t   fid;                 /* Dataspace identifier */
   hid_t   attr1, attr2, attr3; /* Attribute identifiers */
   hid_t   attr;
   hid_t   aid1, aid2, aid3;    /* Attribute dataspace identifiers */ 
   hid_t   aspace;
   hid_t   atype;               /* Attribute type */

   hsize_t fdim[] = {SIZE};
   hsize_t adim[] = {ADIM1, ADIM2};  /* Dimensions of the first attribute  */
   
   float matrix[ADIM1][ADIM2]; /* Attribute data */ 

   H5S_class_t  class;
   herr_t  ret;                /* Return value */
   unsigned i,j;                /* Counters */
   int     idx;                /* Attribute index */
   int     point_out;          /* Buffer to read scalar attribute back */

   /*
    * Data initialization.
    */
   int vector[] = {1, 2, 3, 4, 5, 6, 7};  /* Dataset data */
   int point = 1;                         /* Value of the scalar attribute */ 
   char string[] = {"testwestvestbest"};
   hsize_t  dimsa[2]={2,2};

   
   for (i=0; i < ADIM1; i++) {            /* Values of the array attribute */
       for (j=0; j < ADIM2; j++)
       matrix[i][j] = 9.9;
   }

   file = H5Fcreate(H5FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
   fid = H5Screate(H5S_SIMPLE);
   ret = H5Sset_extent_simple(fid, RANK, fdim, NULL);

   dataset = H5Dcreate(file, "Dataset", H5T_NATIVE_INT, fid, H5P_DEFAULT);
   ret = H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL , H5S_ALL, H5P_DEFAULT, vector);

   /* Create array attribute.  */
   aid1 = H5Screate(H5S_SIMPLE);
   ret  = H5Sset_extent_simple(aid1, ARANK, adim, NULL);
   attr1 = H5Acreate(dataset, ANAME, H5T_NATIVE_FLOAT, aid1, H5P_DEFAULT);
   ret = H5Awrite(attr1, H5T_NATIVE_FLOAT, matrix);

   /* Create scalar attribute.  */
   aid2  = H5Screate(H5S_SCALAR);
   attr2 = H5Acreate(dataset, "Integer attribute", H5T_NATIVE_INT, aid2,
                     H5P_DEFAULT);
   ret = H5Awrite(attr2, H5T_NATIVE_INT, &point); 

   /* Create string attribute.  */
   aid3  = H5Screate_simple (2, dimsa, NULL);
   atype = H5Tcopy(H5T_C_S1);
   ret = H5Tset_size(atype, 4);
   ret = H5Tset_strpad(atype,H5T_STR_NULLTERM);
   attr3 = H5Acreate(dataset, ANAMES, atype, aid3, H5P_DEFAULT);
   ret = H5Awrite(attr3, atype, string); 

   /*  Close attribute and file dataspaces.  */
   ret = H5Sclose(aid1); 
   ret = H5Sclose(aid2); 
   ret = H5Sclose(aid3); 
   ret = H5Sclose(fid); 
   ret = H5Aclose(attr1);
   ret = H5Aclose(attr2);
   ret = H5Aclose(attr3);
 
   /* Close the dataset and file.  */
   ret = H5Dclose(dataset);
   ret = H5Fclose(file);

   /* Reopen the file and dataset.  */
   file = H5Fopen(H5FILE_NAME, H5F_ACC_RDONLY, H5P_DEFAULT);
   dataset = H5Dopen(file,"Dataset");

   /* Get attribute info using iteration function. */
   printf ("\nAttributes for 'Dataset' are:\n");
   idx = H5Aiterate(dataset, NULL, attr_info, NULL);

   /* Close the dataset and the file.  */
   ret = H5Dclose(dataset);
   ret = H5Fclose(file);

   return 0;  
}

/*
 * Operator function.
 */
herr_t 
attr_info(hid_t loc_id, const char *name, void *opdata)
{
    hid_t attr, atype, aspace;  /* Attribute, datatype, dataspace identifiers */
    char    *string_out=NULL;
    int   rank;
    hsize_t sdim[64]; 
    herr_t ret;
    int i, j ;
    size_t size, totsize;
    size_t npoints;             /* Number of elements in the array attribute. */ 
    int point_out;    
    float *float_array;         /* Pointer to the array attribute. */
    H5S_class_t  class;

    /* avoid warnings */
    opdata = opdata;

    /*  Open the attribute using its name.  */    
    attr = H5Aopen_name(loc_id, name);

    /*  Display attribute name.  */
    printf("\nName : ");
    puts(name);

    /* Get attribute datatype, dataspace, rank, and dimensions.  */
    atype  = H5Aget_type(attr);
    aspace = H5Aget_space(attr);
    rank = H5Sget_simple_extent_ndims(aspace);
    ret = H5Sget_simple_extent_dims(aspace, sdim, NULL);

    /* Get dataspace type */
    class = H5Sget_simple_extent_type (aspace);
    printf ("H5Sget_simple_extent_type (aspace) returns: %i\n", class);

    /* Display rank and dimension sizes for the array attribute.  */
    if(rank > 0) {
       printf("Rank : %d \n", rank); 
       printf("Dimension sizes : ");
       for (i=0; i< rank; i++) printf("%d ", (int)sdim[i]);
       printf("\n");
    }

    if (H5T_INTEGER == H5Tget_class(atype)) {
       printf("Type : INTEGER \n");
       ret  = H5Aread(attr, atype, &point_out);
       printf("The value of the attribute \"Integer attribute\" is %d \n", 
               point_out);
    }

    if (H5T_FLOAT == H5Tget_class(atype)) {
       printf("Type : FLOAT \n"); 
       npoints = H5Sget_simple_extent_npoints(aspace);
       float_array = (float *)malloc(sizeof(float)*(int)npoints); 
       ret = H5Aread(attr, atype, float_array);
       printf("Values : ");
       for( i = 0; i < (int)npoints; i++) printf("%f ", float_array[i]); 
       printf("\n");
       free(float_array);
    }

    if (H5T_STRING == H5Tget_class (atype)) {
      printf ("Type: STRING \n");
      size = H5Tget_size (atype);
      printf ("Size of Each String is: %i\n", size);
      totsize = size*sdim[0]*sdim[1];
      string_out = calloc (totsize, sizeof(char));
      ret = H5Aread(attr, atype, string_out);
      printf("The value of the attribute with index 2 is:\n");
      j=0;
      for (i=0; i<totsize; i++) {
        printf ("%c", string_out[i]);
        if (j==3) {
          printf(" ");
          j=0;
        }
        else j++;
      }
      printf ("\n");
    }

    ret = H5Tclose(atype);
    ret = H5Sclose(aspace);
    ret = H5Aclose(attr);

    return 0;
}
