/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Copyright by The HDF Group.                                               *
 * Copyright by the Board of Trustees of the University of Illinois.         *
 * All rights reserved.                                                      *
 *                                                                           *
 * This file is part of HDF5.  The full HDF5 copyright notice, including     *
 * terms governing use, modification, and redistribution, is contained in    *
 * the files COPYING and Copyright.html.  COPYING can be found at the root   *
 * of the source code distribution tree; Copyright.html can be found at the  *
 * root level of an installed copy of the electronic HDF5 document set and   *
 * is linked from the top-level documents page.  It can also be found at     *
 * http://hdfgroup.org/HDF5/doc/Copyright.html.  If you do not have          *
 * access to either file, you may request a copy from help@hdfgroup.org.     *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include <string.h>
#include "hdf5.h"

/*
 *  this example demonstrates the usage of the following API functions:
 *
 * (1)
 *  H5Lvisit: recursively visits all links starting from a specified group
 *
 * (2)
 *  H5Lvisit_by_name: recursively visits all links starting from a specified group
 *
 * (3)
 *  H5Ovisit: recursively visits all objects starting from a specified object
 *
 *  (4)
 *  H5Ovisit_by_name: recursively visits all objects starting from a specified object
 */


/*
 *  prototypes for the callback functions for each pair H5Lvisit/H5Lvisit_by_name
 *  and H5Ovisit/H5Ovisit_by_name
 *
 */

static int my_link_visit_cb(hid_t g_id, const char *name, const H5L_info_t *info, void *op_data);
static int my_obj_visit_cb(hid_t o_id, const char *name, const H5O_info_t *info, void *op_data);


/*
 *  main program
 *
 */
int main (void)
{
    char  op_data[20];    /* user-data for visiting */
    hid_t fid;            /* file ID */
    hid_t gid;            /* group ID */
    hid_t sid;            /* space ID */
    hid_t did;            /* dataset ID */
    hid_t tid;            /* named type ID */
 
    
   /*
    * create a new file using H5F_ACC_TRUNC access,
    * default file creation properties, and default file
    * access properties.
    */
    fid = H5Fcreate("visit.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);

   /*-------------------------------------------------------------------------
    * populate the file with objects and links
    *-------------------------------------------------------------------------
    */

    /* create a group */
    gid = H5Gcreate2(fid, "g1", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);

    /* create a soft link to the group created */
    H5Lcreate_soft("g1", fid, "soft link to g1", H5P_DEFAULT, H5P_DEFAULT);

    /* create a hard link to the group created */
    H5Lcreate_hard(fid, "g1", fid, "hard link to g1", H5P_DEFAULT, H5P_DEFAULT);

    /* create a dataset in the group */
    sid = H5Screate(H5S_SCALAR);
    did = H5Dcreate2(fid, "g1/dset", H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);

    /* create named datatype in the group */
    tid = H5Tcopy(H5T_NATIVE_INT);
    H5Tcommit2(fid, "g1/type", tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
    
   /*-------------------------------------------------------------------------
    * call  H5Lvisit
    * H5Lvisit recursively visits all links starting from a specified group
    * in this call we use the file ID as the starting point, thus iterating
    * trough all links in the file; we do not use the user defined data
    * parameter
    *-------------------------------------------------------------------------
    */

    printf("H5Lvisit call ...\n");

    H5Lvisit(fid, H5_INDEX_NAME, H5_ITER_INC, my_link_visit_cb, NULL);

   /*-------------------------------------------------------------------------
    * call  H5Lvisit_by_name
    * H5Lvisit_by_name recursively visits all links starting from a specified 
    * pair ID/NAME (first 2 parameters); in this call we use the pair file ID
    * and "g1" as the starting point, thus iterating trough all links in the
    * group "g1"; the user defined data parameter contains a name to be found
    *-------------------------------------------------------------------------
    */

    printf("H5Lvisit_by_name call ...\n");

    /* initialize name to be found */
    strcpy(op_data,"dset");

    H5Lvisit_by_name(fid, "g1", H5_INDEX_NAME, H5_ITER_INC, my_link_visit_cb, &op_data, H5P_DEFAULT);


   /*-------------------------------------------------------------------------
    * call  H5Ovisit
    * H5Ovisit recursively visits all objects starting from a specified object.
    * in this call we use the file ID as the starting point, thus iterating
    * trough all objects in the file; we do not use the user defined data
    * parameter
    *-------------------------------------------------------------------------
    */

    printf("H5Ovisit call ...\n");

    H5Ovisit(fid, H5_INDEX_NAME, H5_ITER_INC, my_obj_visit_cb, NULL);

   /*-------------------------------------------------------------------------
    * call  H5Ovisit_by_name
    * H5Ovisit_by_name recursively visits all objects starting from a specified 
    * pair ID/NAME (first 2 parameters); in this call we use the pair file ID
    * and "g1" as the starting point, thus iterating trough all objects in the
    * group "g1"; the user defined data parameter contains a name to be found
    *-------------------------------------------------------------------------
    */

    printf("H5Ovisit_by_name call ...\n");

    H5Ovisit_by_name(fid, "g1", H5_INDEX_NAME, H5_ITER_INC, my_obj_visit_cb, &op_data, H5P_DEFAULT);

    
    /* close */
    H5Dclose(did);
    H5Sclose(sid);
    H5Gclose(gid);
    H5Tclose(tid);
    H5Fclose(fid);
    
    return 0;
}



/*-------------------------------------------------------------------------
 * Function: my_link_visit_cb
 *
 * Purpose: callback function used by H5Lvisit/H5Lvisit_by_name
 *   It prints the type of link (soft link or hard link) and if the 
 *   user defined data matches a name found in the traversal, it
 *   prints that the name was found and its file adress
 *
 *-------------------------------------------------------------------------
 */

static int 
my_link_visit_cb(hid_t g_id, const char *name, const H5L_info_t *info, void *op_data)
{
    printf(" visiting... '%s'", name ); 

    if (info->type == H5L_TYPE_SOFT)
    {

        printf(" type is soft link"); 

    }
    else if (info->type == H5L_TYPE_HARD)
    {

        printf(" type is hard link"); 

    }

    if (op_data)
    {
        char *s = (char*) op_data;

        if (strcmp(s,name) == 0)
        {

            printf(" ...found '%s' and its adress is %d",s,(int)info->u.address); 
        }

       

    }

    printf("\n"); 

    
    return(H5_ITER_CONT);
} 


/*-------------------------------------------------------------------------
 * Function: my_obj_visit_cb
 *
 * Purpose: callback function used by H5Ovisit/H5Ovisit_by_name
 *   It prints the type of object (group, dataset or named datatype) and if the 
 *   user defined data matches a name found in the traversal, it
 *   prints that the name was found and its file adress
 *
 *-------------------------------------------------------------------------
 */

static int 
my_obj_visit_cb(hid_t o_id, const char *name, const H5O_info_t *info, void *op_data)
{
    printf(" visiting... '%s'", name ); 

    if (info->type == H5O_TYPE_GROUP)
    {

        printf(" object is a group"); 

    }
    else if (info->type == H5O_TYPE_DATASET)
    {

        printf(" object is a dataset"); 

    }
    else if (info->type == H5O_TYPE_NAMED_DATATYPE)
    {

        printf(" object is a named data type"); 

    }

    if (op_data)
    {
        char *s = (char*) op_data;

        if (strcmp(s,name) == 0)
        {

            printf(" ...found '%s' and its adress is %d",s,(int)info->addr); 
        }
   

    }

    printf("\n"); 
    
    
    
    return(H5_ITER_CONT);
} 

