/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Copyright by The HDF Group.                                               *
 * 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 LICENSE file, which can be found at the root of the source code       *
 * distribution tree, or in https://www.hdfgroup.org/licenses.               *
 * If you do not have access to either file, you may request a copy from     *
 * help@hdfgroup.org.                                                        *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#ifndef H5Epublic_H
#define H5Epublic_H

#include <stdio.h> 

#include "H5public.h"  
#include "H5Ipublic.h" 

#define H5E_DEFAULT 0 

typedef enum H5E_type_t { H5E_MAJOR, H5E_MINOR } H5E_type_t;

typedef struct H5E_error2_t {
    hid_t cls_id;
    
    hid_t maj_num;
    
    hid_t min_num;
    
    unsigned line;
    
    const char *func_name;
    
    const char *file_name;
    
    const char *desc;
    
} H5E_error2_t;

#ifdef __cplusplus
extern "C" {
#endif
#define H5E_ERR_CLS (H5OPEN H5E_ERR_CLS_g)
H5_DLLVAR hid_t H5E_ERR_CLS_g;
#ifdef __cplusplus
}
#endif

#include "H5Epubgen.h"

#ifndef H5_NO_DEPRECATED_SYMBOLS
#define H5E_BEGIN_TRY                                                                                        \
    {                                                                                                        \
        unsigned H5E_saved_is_v2;                                                                            \
        union {                                                                                              \
            H5E_auto1_t efunc1;                                                                              \
            H5E_auto2_t efunc2;                                                                              \
        } H5E_saved;                                                                                         \
        void *H5E_saved_edata;                                                                               \
                                                                                                             \
        (void)H5Eauto_is_v2(H5E_DEFAULT, &H5E_saved_is_v2);                                                  \
        if (H5E_saved_is_v2) {                                                                               \
            (void)H5Eget_auto2(H5E_DEFAULT, &H5E_saved.efunc2, &H5E_saved_edata);                            \
            (void)H5Eset_auto2(H5E_DEFAULT, NULL, NULL);                                                     \
        }                                                                                                    \
        else {                                                                                               \
            (void)H5Eget_auto1(&H5E_saved.efunc1, &H5E_saved_edata);                                         \
            (void)H5Eset_auto1(NULL, NULL);                                                                  \
        }

#define H5E_END_TRY                                                                                          \
    if (H5E_saved_is_v2)                                                                                     \
        (void)H5Eset_auto2(H5E_DEFAULT, H5E_saved.efunc2, H5E_saved_edata);                                  \
    else                                                                                                     \
        (void)H5Eset_auto1(H5E_saved.efunc1, H5E_saved_edata);                                               \
    }
#else 
#define H5E_BEGIN_TRY                                                                                        \
    {                                                                                                        \
        H5E_auto2_t saved_efunc;                                                                             \
        void       *H5E_saved_edata;                                                                         \
                                                                                                             \
        (void)H5Eget_auto2(H5E_DEFAULT, &saved_efunc, &H5E_saved_edata);                                     \
        (void)H5Eset_auto2(H5E_DEFAULT, NULL, NULL);

#define H5E_END_TRY                                                                                          \
    (void)H5Eset_auto2(H5E_DEFAULT, saved_efunc, H5E_saved_edata);                                           \
    }
#endif 

#define H5Epush_sim(func, cls, maj, min, str)                                                                \
    H5Epush2(H5E_DEFAULT, __FILE__, func, __LINE__, cls, maj, min, str)

#define H5Epush_ret(func, cls, maj, min, str, ret)                                                           \
    do {                                                                                                     \
        H5Epush2(H5E_DEFAULT, __FILE__, func, __LINE__, cls, maj, min, str);                                 \
        return (ret);                                                                                        \
    } while (0)

#define H5Epush_goto(func, cls, maj, min, str, label)                                                        \
    do {                                                                                                     \
        H5Epush2(H5E_DEFAULT, __FILE__, func, __LINE__, cls, maj, min, str);                                 \
        goto label;                                                                                          \
    } while (0)

typedef enum H5E_direction_t {
    H5E_WALK_UPWARD   = 0, 
    H5E_WALK_DOWNWARD = 1  
} H5E_direction_t;

#ifdef __cplusplus
extern "C" {
#endif

//! <!-- [H5E_walk2_t_snip] -->

typedef herr_t (*H5E_walk2_t)(unsigned n, const H5E_error2_t *err_desc, void *client_data);
//! <!-- [H5E_walk2_t_snip] -->

//! <!-- [H5E_auto2_t_snip] -->

typedef herr_t (*H5E_auto2_t)(hid_t estack, void *client_data);
//! <!-- [H5E_auto2_t_snip] -->

H5_DLL hid_t H5Eregister_class(const char *cls_name, const char *lib_name, const char *version);

H5_DLL herr_t H5Eunregister_class(hid_t class_id);

H5_DLL herr_t H5Eclose_msg(hid_t err_id);

H5_DLL hid_t H5Ecreate_msg(hid_t cls, H5E_type_t msg_type, const char *msg);

H5_DLL hid_t H5Ecreate_stack(void);

H5_DLL hid_t H5Eget_current_stack(void);

H5_DLL herr_t H5Eappend_stack(hid_t dst_stack_id, hid_t src_stack_id, bool close_source_stack);

H5_DLL herr_t H5Eis_paused(hid_t stack_id, bool *is_paused);

H5_DLL herr_t H5Epause_stack(hid_t stack_id);

H5_DLL herr_t H5Eresume_stack(hid_t stack_id);

H5_DLL herr_t H5Eclose_stack(hid_t stack_id);

H5_DLL ssize_t H5Eget_class_name(hid_t class_id, char *name, size_t size);

H5_DLL herr_t H5Eset_current_stack(hid_t err_stack_id);

H5_DLL herr_t H5Epush2(hid_t err_stack, const char *file, const char *func, unsigned line, hid_t cls_id,
                       hid_t maj_id, hid_t min_id, const char *msg, ...);

H5_DLL herr_t H5Epop(hid_t err_stack, size_t count);

H5_DLL herr_t H5Eprint2(hid_t err_stack, FILE *stream);

H5_DLL herr_t H5Ewalk2(hid_t err_stack, H5E_direction_t direction, H5E_walk2_t func, void *client_data);

H5_DLL herr_t H5Eget_auto2(hid_t estack_id, H5E_auto2_t *func, void **client_data);

H5_DLL herr_t H5Eset_auto2(hid_t estack_id, H5E_auto2_t func, void *client_data);

H5_DLL herr_t H5Eclear2(hid_t err_stack);

H5_DLL herr_t H5Eauto_is_v2(hid_t err_stack, unsigned *is_stack);

H5_DLL ssize_t H5Eget_msg(hid_t msg_id, H5E_type_t *type, char *msg, size_t size);

H5_DLL ssize_t H5Eget_num(hid_t error_stack_id);

#ifndef H5_NO_DEPRECATED_SYMBOLS

typedef hid_t H5E_major_t;
typedef hid_t H5E_minor_t;

typedef struct H5E_error1_t {
    H5E_major_t maj_num;   
    H5E_minor_t min_num;   
    const char *func_name; 
    const char *file_name; 
    unsigned    line;      
    const char *desc;      
} H5E_error1_t;

//! <!-- [H5E_walk1_t_snip] -->

typedef herr_t (*H5E_walk1_t)(int n, H5E_error1_t *err_desc, void *client_data);
//! <!-- [H5E_walk1_t_snip] -->

//! <!-- [H5E_auto1_t_snip] -->

typedef herr_t (*H5E_auto1_t)(void *client_data);
//! <!-- [H5E_auto1_t_snip] -->

H5_DLL herr_t H5Eclear1(void);

H5_DLL herr_t H5Eget_auto1(H5E_auto1_t *func, void **client_data);

H5_DLL herr_t H5Epush1(const char *file, const char *func, unsigned line, H5E_major_t maj, H5E_minor_t min,
                       const char *str);

H5_DLL herr_t H5Eprint1(FILE *stream);

H5_DLL herr_t H5Eset_auto1(H5E_auto1_t func, void *client_data);

H5_DLL herr_t H5Ewalk1(H5E_direction_t direction, H5E_walk1_t func, void *client_data);

H5_DLL char *H5Eget_major(H5E_major_t maj);

H5_DLL char *H5Eget_minor(H5E_minor_t min);
#endif 

#ifdef __cplusplus
}
#endif

#endif 
