/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * 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 H5private_H
#define H5private_H

#define __STDC_WANT_IEC_60559_TYPES_EXT__

#include "H5public.h" 

#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <fenv.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include <float.h>
#include <math.h>

#ifdef H5_HAVE_COMPLEX_NUMBERS
#include <complex.h>
#endif

#define R_NO_REMAP 1
#include <R_ext/Print.h>
#include <R_ext/Error.h>

H5_DLL extern FILE *Rstdout;
H5_DLL extern FILE *Rstderr;

#ifdef __cplusplus
extern "C" {
#endif

H5_DLL int Rfprintf(FILE *stream, const char *format, ...);
H5_DLL int Rfputs(const char *s, FILE *stream);
H5_DLL void Rabort(void);
H5_DLL void Rexit(int status);

#ifdef __cplusplus
}
#endif

#ifdef H5_HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef H5_HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef H5_HAVE_PWD_H
#include <pwd.h>
#endif
#ifdef H5_HAVE_WAITPID
#include <sys/wait.h>
#endif

#if defined(H5_HAVE_THREADS)

#if defined(H5_HAVE_THREADS_H)
#include <threads.h>
#endif

#if defined(H5_HAVE_PTHREAD_H)
#include <pthread.h>
#endif
#endif

#if defined(H5_HAVE_STDATOMIC_H) && !defined(__cplusplus)
#include <stdatomic.h>
#endif

#ifdef H5_HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif

#if defined(H5_HAVE_FLOCK) && defined(H5_HAVE_SYS_FILE_H)
#include <sys/file.h>
#endif

#ifdef H5_HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif

#ifdef H5_HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif

#ifdef H5_HAVE_DLFCN_H
#include <dlfcn.h>
#endif
#ifdef H5_HAVE_DIRENT_H
#include <dirent.h>
#endif

#define H5_DEFAULT_VFD      H5FD_SEC2
#define H5_DEFAULT_VFD_NAME "sec2"

#define H5_DEFAULT_VOL H5VL_NATIVE_conn_g

#ifdef H5_HAVE_WIN32_API

#define WIN32_LEAN_AND_MEAN 
#define NOGDI               

#if defined(H5_HAVE_MINGW) && defined(H5_HAVE_THREADS)
#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600)
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0600
#endif
#endif

#include <windows.h>

#include <direct.h>   
#include <io.h>       
#include <winsock2.h> 
#include <shlwapi.h>  

#endif 

#include "H5warnings.h"

#ifndef F_OK
#define F_OK 00
#define W_OK 02
#define R_OK 04
#endif

#define uthash_malloc(sz)    H5MM_malloc(sz)
#define uthash_free(ptr, sz) H5MM_free(ptr) 
#define HASH_NONFATAL_OOM    1              
#include "uthash.h"

#if defined(H5_HAVE_ATTRIBUTE)
#   define H5_ATTR_FORMAT(X, Y, Z) __attribute__((format(X, Y, Z)))
#   define H5_ATTR_UNUSED          __attribute__((unused))

#   ifdef H5_HAVE_PARALLEL
#       define H5_ATTR_PARALLEL_UNUSED __attribute__((unused))
#       define H5_ATTR_PARALLEL_USED   
#   else
#       define H5_ATTR_PARALLEL_UNUSED 
#       define H5_ATTR_PARALLEL_USED   __attribute__((unused))
#   endif

#   ifdef H5_NO_DEPRECATED_SYMBOLS
#       define H5_ATTR_DEPRECATED_USED H5_ATTR_UNUSED
#   else
#       define H5_ATTR_DEPRECATED_USED 
#   endif

#   ifndef NDEBUG
#       define H5_ATTR_NDEBUG_UNUSED 
#   else
#       define H5_ATTR_NDEBUG_UNUSED H5_ATTR_UNUSED
#   endif

#   define H5_ATTR_NORETURN __attribute__((noreturn))
#   define H5_ATTR_CONST    __attribute__((const))
#   define H5_ATTR_PURE     __attribute__((pure))

#   if defined(__clang__) || defined(__GNUC__) && __GNUC__ >= 7 && !defined(__INTEL_COMPILER)
#       define H5_ATTR_FALLTHROUGH __attribute__((fallthrough));
#   else
#       define H5_ATTR_FALLTHROUGH 
#   endif

#  if defined(__GNUC__) && !defined(__INTEL_COMPILER)
#       define H5_ATTR_MALLOC __attribute__((malloc))
#  else
#       define H5_ATTR_MALLOC 
#  endif

#  if defined(__clang__)
#       define H5_ATTR_NO_OPTIMIZE __attribute__((optnone))
#  else
#       define H5_ATTR_NO_OPTIMIZE 
#  endif

#  if defined(__clang__)
#       define H5_ATTR_THREAD_ANNOT(X) __attribute__((X))
#  else
#       define H5_ATTR_THREAD_ANNOT(X) 
#  endif

#else
#   define H5_ATTR_FORMAT(X, Y, Z) 
#   define H5_ATTR_UNUSED          
#   define H5_ATTR_NDEBUG_UNUSED   
#   define H5_ATTR_DEPRECATED_USED 
#   define H5_ATTR_PARALLEL_UNUSED 
#   define H5_ATTR_PARALLEL_USED   
#   define H5_ATTR_NORETURN        
#   define H5_ATTR_CONST           
#   define H5_ATTR_PURE            
#   define H5_ATTR_FALLTHROUGH     
#   define H5_ATTR_MALLOC          
#   define H5_ATTR_NO_OPTIMIZE     
#   define H5_ATTR_THREAD_ANNOT(X) 
#endif

#ifdef H5_HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef H5_HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef H5_HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef H5_HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif

#define SUCCEED 0
#define FAIL    (-1)

#ifndef NELMTS
#define NELMTS(X) (sizeof(X) / sizeof(X[0]))
#endif

#undef MIN
#define MIN(a, b)        (((a) < (b)) ? (a) : (b))
#define MIN2(a, b)       MIN(a, b)
#define MIN3(a, b, c)    MIN(a, MIN(b, c))
#define MIN4(a, b, c, d) MIN(MIN(a, b), MIN(c, d))

#undef MAX
#define MAX(a, b)        (((a) > (b)) ? (a) : (b))
#define MAX2(a, b)       MAX(a, b)
#define MAX3(a, b, c)    MAX(a, MAX(b, c))
#define MAX4(a, b, c, d) MAX(MAX(a, b), MAX(c, d))

#define RANGE(LO, X, HI) MAX(LO, MIN(X, HI))

#define H5_RANGE_OVERLAP(L1, H1, L2, H2) (!((L1) > (H2) || (L2) > (H1)))

#ifndef ABS
#define ABS(a) (((a) >= 0) ? (a) : -(a))
#endif

#define POWER_OF_TWO(n) (!(n & (n - 1)) && n)

#define H5_EXP2(n) (1 << (n))

#define H5_IS_BUFFER_OVERFLOW(ptr, size, buffer_end)                                                         \
    (                                                                                                        \
                                                                                           \
      ((size) != 0) &&                                                                                       \
      (                                                                                                      \
                                                                                       \
        ((ptr) > (buffer_end)) ||                                                                            \
                                                     \
        (((size_t)(size) <= PTRDIFF_MAX) && ((ptrdiff_t)(size) < 0)) ||                                      \
                                                                                       \
        ((size_t)(size) > (size_t)((((const uint8_t *)buffer_end) - ((const uint8_t *)ptr)) + 1))            \
      )                                                                                                      \
    )

#define H5_IS_KNOWN_BUFFER_OVERFLOW(skip, ptr, size, buffer_end)                                             \
    (skip ? false : H5_IS_BUFFER_OVERFLOW(ptr, size, buffer_end))

#ifndef SSIZE_MAX
#define SSIZE_MAX SSIZE_T_MAX
#endif

#define HSIZET_MAX  ((hsize_t)ULLONG_MAX)
#define HSSIZET_MAX ((hssize_t)LLONG_MAX)
#define HSSIZET_MIN (~(HSSIZET_MAX))

#ifdef H5_HAVE_PARALLEL

#if SIZE_MAX == UCHAR_MAX
#define H5_SIZE_T_AS_MPI_TYPE MPI_UNSIGNED_CHAR
#elif SIZE_MAX == USHRT_MAX
#define H5_SIZE_T_AS_MPI_TYPE MPI_UNSIGNED_SHORT
#elif SIZE_MAX == UINT_MAX
#define H5_SIZE_T_AS_MPI_TYPE MPI_UNSIGNED
#elif SIZE_MAX == ULONG_MAX
#define H5_SIZE_T_AS_MPI_TYPE MPI_UNSIGNED_LONG
#elif SIZE_MAX == ULLONG_MAX
#define H5_SIZE_T_AS_MPI_TYPE MPI_UNSIGNED_LONG_LONG
#else
#error "no suitable MPI type for size_t"
#endif

#endif 

#if defined(H5_HAVE_WIN32_API)
#define h5_posix_io_t         unsigned int
#define h5_posix_io_ret_t     int
#define H5_POSIX_MAX_IO_BYTES INT_MAX
#elif defined(H5_HAVE_DARWIN)
#define h5_posix_io_t         size_t
#define h5_posix_io_ret_t     ssize_t
#define H5_POSIX_MAX_IO_BYTES INT_MAX
#else
#define h5_posix_io_t         size_t
#define h5_posix_io_ret_t     ssize_t
#define H5_POSIX_MAX_IO_BYTES SSIZE_MAX
#endif

#if defined(H5_HAVE_WIN32_API)
#define H5_POSIX_CREATE_MODE_RW (_S_IREAD | _S_IWRITE)
#else
#define H5_POSIX_CREATE_MODE_RW 0666
#endif

#define H5_REQUEST_NULL NULL

#define H5_addr_overflow(X,Z)    (HADDR_UNDEF == (X) ||                     \
                                  HADDR_UNDEF == (X) + (haddr_t)(Z) ||      \
                                  (X) + (haddr_t)(Z) < (X))
#define H5_addr_defined(X)       ((X) != HADDR_UNDEF)

#define H5_addr_eq(X,Y)          ((X) != HADDR_UNDEF && (X) == (Y))
#define H5_addr_ne(X,Y)          (!H5_addr_eq((X),(Y)))
#define H5_addr_lt(X,Y)          ((X) != HADDR_UNDEF &&                     \
                                  (Y) != HADDR_UNDEF &&                     \
                                  (X) < (Y))
#define H5_addr_le(X,Y)          ((X) != HADDR_UNDEF &&                     \
                                  (Y) != HADDR_UNDEF &&                     \
                                  (X) <= (Y))
#define H5_addr_gt(X,Y)          ((X) != HADDR_UNDEF &&                     \
                                  (Y) != HADDR_UNDEF &&                     \
                                  (X) > (Y))
#define H5_addr_ge(X,Y)          ((X) != HADDR_UNDEF &&                     \
                                  (Y) != HADDR_UNDEF &&                     \
                                  (X) >= (Y))
#define H5_addr_cmp(X,Y)         (H5_addr_eq((X), (Y)) ? 0 :                \
                                 (H5_addr_lt((X), (Y)) ? -1 : 1))
#define H5_addr_overlap(O1,L1,O2,L2) H5_RANGE_OVERLAP(O1, ((O1)+(L1)-1), O2, ((O2)+(L2)-1))

#define H5_FLT_ABS_EQUAL(X, Y)  (fabsf((X) - (Y)) < FLT_EPSILON)
#define H5_DBL_ABS_EQUAL(X, Y)  (fabs((X) - (Y)) < DBL_EPSILON)
#define H5_LDBL_ABS_EQUAL(X, Y) (fabsl((X) - (Y)) < LDBL_EPSILON)

#ifdef H5_HAVE__FLOAT16
#ifdef H5_HAVE_FABSF16
#define H5_FLT16_ABS_EQUAL(X, Y) (fabsf16((X) - (Y)) < FLT16_EPSILON)
#else
#define H5_FLT16_ABS_EQUAL(X, Y) H5_FLT_ABS_EQUAL((float)X, (float)Y)
#endif
#endif

#define H5_FLT_REL_EQUAL(X, Y, M)  (fabsf(((Y) - (X)) / (X)) < (M))
#define H5_DBL_REL_EQUAL(X, Y, M)  (fabs(((Y) - (X)) / (X)) < (M))
#define H5_LDBL_REL_EQUAL(X, Y, M) (fabsl(((Y) - (X)) / (X)) < (M))

#ifdef H5_HAVE__FLOAT16
#ifdef H5_HAVE_FABSF16
#define H5_FLT16_REL_EQUAL(X, Y, M) (fabsf16(((Y) - (X)) / (X)) < (M))
#else
#define H5_FLT16_REL_EQUAL(X, Y, M) H5_FLT_REL_EQUAL((float)X, (float)Y, M)
#endif
#endif

#ifndef H5_HAVE_FLOCK

#define LOCK_SH 0x01
#define LOCK_EX 0x02
#define LOCK_NB 0x04
#define LOCK_UN 0x08
#endif 

typedef union {
    void       *vp;
    const void *cvp;
} H5_flexible_const_ptr_t;

#if defined(H5_HAVE__FLOAT16) && !defined(__cplusplus)
#if defined(__GNUC__)
__extension__ typedef _Float16 H5__Float16;
#else
typedef _Float16 H5__Float16;
#endif
#endif

typedef int (*H5_sort_func_cb_t)(const void *, const void *);

#include "H5timer.h"

H5_DLL char *H5_strcasestr(const char *haystack, const char *needle);

typedef enum {
    H5_COPY_SHALLOW, 
    H5_COPY_DEEP     
} H5_copy_depth_t;

typedef struct H5O_copy_file_ud_common_t {
    struct H5O_pline_t *src_pline; 
} H5O_copy_file_ud_common_t;

typedef struct {
    unsigned long fileno; 
    haddr_t       addr;   
} H5_obj_t;

#define H5_SIZEOF_H5_STAT_SIZE_T H5_SIZEOF_OFF_T

#include "H5win32defs.h"

#ifndef H5_HAVE_WIN32_API
typedef struct stat h5_stat_t;
#endif

#if defined(H5_HAVE_COMPLEX_NUMBERS) && defined(H5_HAVE_C99_COMPLEX_NUMBERS)
typedef float _Complex H5_float_complex;
typedef double _Complex H5_double_complex;
typedef long double _Complex H5_ldouble_complex;
#endif

typedef HDoff_t h5_stat_size_t;

#ifndef HDaccess
#define HDaccess(F, M) access(F, M)
#endif
#ifndef HDchdir
#define HDchdir(S) chdir(S)
#endif
#ifndef HDclose
#define HDclose(F) close(F)
#endif
#ifndef HDclosedir
#define HDclosedir(D) closedir(D)
#endif
#ifndef HDcreat
#define HDcreat(S, M) creat(S, M)
#endif
#ifndef HDfdopen
#define HDfdopen(N, S) fdopen(N, S)
#endif
#ifndef HDfileno
#define HDfileno(F) fileno(F)
#endif

#ifdef H5_HAVE_FCNTL
H5_DLL int Pflock(int fd, int operation);
#endif
H5_DLL H5_ATTR_CONST int Nflock(int fd, int operation);

#ifndef HDflock

#if defined(H5_HAVE_FLOCK)
#define HDflock(F, L) flock(F, L)
#elif defined(H5_HAVE_FCNTL)
#define HDflock(F, L) Pflock(F, L)
#else
#define HDflock(F, L) Nflock(F, L)
#endif

#endif 

#if defined(H5_HAVE_WIN32_API) || defined(H5_HAVE_DARWIN) || (defined(__FreeBSD__) && __FreeBSD__ < 14)
H5_DLL herr_t HDqsort_context(void *base, size_t nel, size_t size,
                              int (*compar)(const void *, const void *, void *), void *arg);
#endif

#ifndef H5_HAVE_QSORT_REENTRANT
H5_DLL herr_t HDqsort_fallback(void *base, size_t nel, size_t size,
                               int (*compar)(const void *, const void *, void *), void *arg);
#endif

#ifndef HDfseek
#define HDfseek(F, O, W) fseeko(F, O, W)
#endif
#ifndef HDfstat
#define HDfstat(F, B) fstat(F, B)
#endif
#ifndef HDftell
#define HDftell(F) ftello(F)
#endif
#ifndef HDftruncate
#define HDftruncate(F, L) ftruncate(F, L)
#endif
#ifndef HDgetcwd
#define HDgetcwd(S, Z) getcwd(S, Z)
#endif
#ifndef HDgetdcwd
#define HDgetdcwd(D, S, Z) getcwd(S, Z)
#endif

#ifndef HDgetdrive
#define HDgetdrive() 0
#endif

#ifndef HDgetpid
#define HDgetpid() getpid()
#endif
#ifndef HDgettimeofday
#define HDgettimeofday(S, P) gettimeofday(S, P)
#endif
#ifndef HDisatty
#define HDisatty(F) isatty(F)
#endif
#ifndef HDlseek
#define HDlseek(F, O, W) lseek(F, O, W)
#endif
#ifndef HDlstat
#define HDlstat(S, B) lstat(S, B)
#endif
#ifndef HDmkdir
#define HDmkdir(S, M) mkdir(S, M)
#endif
#ifndef HDnanosleep
#define HDnanosleep(N, O) nanosleep(N, O)
#endif
#ifndef HDopen
#define HDopen(F, ...) open(F, __VA_ARGS__)
#endif
#ifndef HDopendir
#define HDopendir(S) opendir(S)
#endif
#ifndef HDpread
#define HDpread(F, B, C, O) pread(F, B, C, O)
#endif
#ifndef HDpwrite
#define HDpwrite(F, B, C, O) pwrite(F, B, C, O)
#endif
#ifndef HDread
#define HDread(F, M, Z) read(F, M, Z)
#endif
#ifndef HDreaddir
#define HDreaddir(D) readdir(D)
#endif
#ifndef HDrealpath
#define HDrealpath(F1, F2) realpath(F1, F2)
#endif
#ifndef HDremove
#define HDremove(S) remove(S)
#endif
#ifndef HDrmdir
#define HDrmdir(S) rmdir(S)
#endif
#ifndef HDsetenv
#define HDsetenv(N, V, O) setenv(N, V, O)
#endif
#ifndef HDsetvbuf
#define HDsetvbuf(F, S, M, Z) setvbuf(F, S, M, Z)
#endif
#ifndef HDshutdown
#define HDshutdown(A, B) shutdown((A), (B))
#endif
#ifndef HDsigaction
#define HDsigaction(S, A, O) sigaction((S), (A), (O))
#endif
#ifndef HDsigemptyset
#define HDsigemptyset(S) sigemptyset(S)
#endif
#ifndef HDsleep
#define HDsleep(N) sleep(N)
#endif
#ifndef HDstat
#define HDstat(S, B) stat(S, B)
#endif
#ifndef HDstrcasestr
#if defined(H5_HAVE_STRCASESTR)
#define HDstrcasestr(X, Y) strcasestr(X, Y)
#else
#define HDstrcasestr(X, Y) H5_strcasestr(X, Y)
#endif
#endif
#ifndef HDstrcasecmp
#define HDstrcasecmp(X, Y) strcasecmp(X, Y)
#endif
#ifndef HDstrndup
#define HDstrndup(S, N) strndup(S, N)
#endif
#ifndef HDstrtok_r
#define HDstrtok_r(X, Y, Z) strtok_r(X, Y, Z)
#endif
#ifndef HDunlink
#define HDunlink(S) unlink(S)
#endif
#ifndef HDunsetenv
#define HDunsetenv(S) unsetenv(S)
#endif
#ifndef HDqsort_r
#ifdef H5_HAVE_QSORT_REENTRANT
#if defined(H5_HAVE_DARWIN) || (defined(__FreeBSD__) && __FreeBSD__ < 14)

#define HDqsort_r(B, N, S, C, A) HDqsort_context(B, N, S, C, A)
#else

#define HDqsort_r(B, N, S, C, A) (qsort_r(B, N, S, C, A), SUCCEED)
#endif
#else

#define HDqsort_r(B, N, S, C, A) HDqsort_fallback(B, N, S, C, A)
#endif
#endif
#ifndef HDvasprintf
#ifdef H5_HAVE_VASPRINTF
#define HDvasprintf(RET, FMT, A) vasprintf(RET, FMT, A)
#else
H5_DLL int HDvasprintf(char **bufp, const char *fmt, va_list _ap);
#endif
#endif

#ifndef HDwrite
#define HDwrite(F, M, Z) write(F, M, Z)
#endif

#ifdef H5_HAVE_COMPLEX_NUMBERS
#ifndef H5_CMPLXF
#define H5_CMPLXF(real, imag)                                                                                \
    ((H5_float_complex)((float)(real) + (float)(imag) * (H5_float_complex)_Complex_I))
#endif
#ifndef H5_CMPLX
#define H5_CMPLX(real, imag)                                                                                 \
    ((H5_double_complex)((double)(real) + (double)(imag) * (H5_double_complex)_Complex_I))
#endif
#ifndef H5_CMPLXL
#define H5_CMPLXL(real, imag)                                                                                \
    ((H5_ldouble_complex)((long double)(real) + (long double)(imag) * (H5_ldouble_complex)_Complex_I))
#endif
#endif

#define H5_STRINGIZE(x) #x
#define H5_TOSTRING(x)  H5_STRINGIZE(x)

#define H5_GLUE(x, y)        x##y
#define H5_GLUE3(x, y, z)    x##y##z
#define H5_GLUE4(w, x, y, z) w##x##y##z

#ifndef NDEBUG
#define H5_CHECK_OVERFLOW(var, vartype, casttype)                                                            \
    do {                                                                                                     \
        casttype _tmp_overflow = (casttype)(var);                                                            \
        assert((var) == (vartype)_tmp_overflow);                                                             \
    } while (0)
#else 
#define H5_CHECK_OVERFLOW(var, vartype, casttype)
#endif 

#ifndef NDEBUG
#define ASSIGN_TO_SMALLER_SIZE(dst, dsttype, src, srctype)                                                   \
    {                                                                                                        \
        srctype _tmp_src = (srctype)(src);                                                                   \
        dsttype _tmp_dst = (dsttype)(_tmp_src);                                                              \
        assert(_tmp_src == (srctype)_tmp_dst);                                                               \
        (dst) = _tmp_dst;                                                                                    \
    }

#define ASSIGN_TO_LARGER_SIZE_SAME_SIGNED(dst, dsttype, src, srctype) (dst) = (dsttype)(src);

#define ASSIGN_TO_LARGER_SIZE_SIGNED_TO_UNSIGNED(dst, dsttype, src, srctype)                                 \
    {                                                                                                        \
        srctype _tmp_src = (srctype)(src);                                                                   \
        dsttype _tmp_dst = (dsttype)(_tmp_src);                                                              \
        assert(_tmp_src >= 0);                                                                               \
        assert(_tmp_src == (srctype)_tmp_dst);                                                               \
        (dst) = _tmp_dst;                                                                                    \
    }

#define ASSIGN_TO_LARGER_SIZE_UNSIGNED_TO_SIGNED(dst, dsttype, src, srctype) (dst) = (dsttype)(src);

#define ASSIGN_TO_SAME_SIZE_UNSIGNED_TO_SIGNED(dst, dsttype, src, srctype)                                   \
    {                                                                                                        \
        srctype _tmp_src = (srctype)(src);                                                                   \
        dsttype _tmp_dst = (dsttype)(_tmp_src);                                                              \
        assert(_tmp_dst >= 0);                                                                               \
        assert(_tmp_src == (srctype)_tmp_dst);                                                               \
        (dst) = _tmp_dst;                                                                                    \
    }

#define ASSIGN_TO_SAME_SIZE_SIGNED_TO_UNSIGNED(dst, dsttype, src, srctype)                                   \
    {                                                                                                        \
        srctype _tmp_src = (srctype)(src);                                                                   \
        dsttype _tmp_dst = (dsttype)(_tmp_src);                                                              \
        assert(_tmp_src >= 0);                                                                               \
        assert(_tmp_src == (srctype)_tmp_dst);                                                               \
        (dst) = _tmp_dst;                                                                                    \
    }

#define ASSIGN_TO_SAME_SIZE_SAME_SIGNED(dst, dsttype, src, srctype) (dst) = (dsttype)(src);

#include "H5overflow.h"

#define H5_CHECKED_ASSIGN(dst, dsttype, src, srctype)                                                        \
    do {                                                                                                     \
        ASSIGN_##srctype##_TO_##dsttype(dst, dsttype, src, srctype)                                          \
    } while (0)

#else 
#define H5_CHECKED_ASSIGN(dst, dsttype, src, srctype)                                                        \
    do {                                                                                                     \
        (dst) = (dsttype)(src);                                                                              \
    } while (0)
#endif 

#if defined(H5_HAVE_WINDOW_PATH)

#define H5_DIR_SLASH_SEPC      '/'
#define H5_DIR_SEPC            '\\'
#define H5_DIR_SEPS            "\\"
#define H5_CHECK_DELIMITER(SS) ((SS == H5_DIR_SEPC) || (SS == H5_DIR_SLASH_SEPC))
#define H5_CHECK_ABSOLUTE(NAME)                                                                              \
    ((isalpha((unsigned char)NAME[0])) && (NAME[1] == ':') && (H5_CHECK_DELIMITER(NAME[2])))
#define H5_CHECK_ABS_DRIVE(NAME) ((isalpha((unsigned char)NAME[0])) && (NAME[1] == ':'))
#define H5_CHECK_ABS_PATH(NAME)  (H5_CHECK_DELIMITER(NAME[0]))

#define H5_GET_LAST_DELIMITER(NAME, ptr)                                                                     \
    {                                                                                                        \
        char *slash, *backslash;                                                                             \
                                                                                                             \
        slash     = strrchr(NAME, H5_DIR_SLASH_SEPC);                                                        \
        backslash = strrchr(NAME, H5_DIR_SEPC);                                                              \
        if (backslash > slash)                                                                               \
            (ptr = backslash);                                                                               \
        else                                                                                                 \
            (ptr = slash);                                                                                   \
    }

#else 

#define H5_DIR_SEPC                      '/'
#define H5_DIR_SEPS                      "/"
#define H5_CHECK_DELIMITER(SS)           (SS == H5_DIR_SEPC)
#define H5_CHECK_ABSOLUTE(NAME)          (H5_CHECK_DELIMITER(*NAME))
#define H5_CHECK_ABS_DRIVE(NAME)         (0)
#define H5_CHECK_ABS_PATH(NAME)          (0)
#define H5_GET_LAST_DELIMITER(NAME, ptr) ptr = strrchr(NAME, H5_DIR_SEPC);

#endif 

#define H5_COLON_SEPC ':'

typedef enum {
    H5_PKG_A,  
    H5_PKG_AC, 
    H5_PKG_B,  
    H5_PKG_D,  
    H5_PKG_E,  
    H5_PKG_F,  
    H5_PKG_G,  
    H5_PKG_HG, 
    H5_PKG_HL, 
    H5_PKG_I,  
    H5_PKG_M,  
    H5_PKG_MF, 
    H5_PKG_MM, 
    H5_PKG_O,  
    H5_PKG_P,  
    H5_PKG_S,  
    H5_PKG_T,  
    H5_PKG_V,  
    H5_PKG_VL, 
    H5_PKG_Z,  
    H5_NPKGS   
} H5_pkg_t;

typedef struct H5_debug_open_stream_t {
    FILE                          *stream; 
    struct H5_debug_open_stream_t *next;   
} H5_debug_open_stream_t;

typedef struct H5_debug_t {
    FILE *trace;  
    bool  ttop;   
    bool  ttimes; 
    struct {
        const char *name;   
        FILE       *stream; 
    } pkg[H5_NPKGS];
    H5_debug_open_stream_t *open_stream; 
} H5_debug_t;

#ifdef H5_HAVE_PARALLEL

#define H5_CHECK_MPI_VERSION(mpi_version, mpi_subversion)                                                    \
    ((MPI_VERSION > (mpi_version)) ||                                                                        \
     ((MPI_VERSION == (mpi_version)) && (MPI_SUBVERSION >= (mpi_subversion))))

extern bool H5_coll_api_sanity_check_g;
#endif 

extern H5_debug_t H5_debug_g;
#define H5DEBUG(X) (H5_debug_g.pkg[H5_PKG_##X].stream)

extern const char H5build_settings[];

#include "H5Eprivate.h"
typedef struct H5_user_cb_state_t {
    H5E_user_cb_state_t h5e_state; 
} H5_user_cb_state_t;

#define H5_BEFORE_USER_CB(err)                                                                               \
    {                                                                                                        \
        H5_user_cb_state_t state;                                                                            \
                                                                                                             \
        if (H5_user_cb_prepare(&state) < 0)                                                                  \
            HGOTO_ERROR(H5E_LIB, H5E_CANTSET, (err), "preparation for user callback failed");

#define H5_AFTER_USER_CB(err)                                                                                \
    if (H5_user_cb_restore(&state) < 0)                                                                      \
        HGOTO_ERROR(H5E_LIB, H5E_CANTRESTORE, (err), "preparation for user callback failed");                \
    }

#define H5_BEFORE_USER_CB_NOERR(err)                                                                         \
    {                                                                                                        \
        H5_user_cb_state_t state;                                                                            \
                                                                                                             \
        if (H5_user_cb_prepare(&state) < 0)                                                                  \
            ret_value = (err);                                                                               \
        else {

#define H5_AFTER_USER_CB_NOERR(err)                                                                          \
    if (H5_user_cb_restore(&state) < 0)                                                                      \
        ret_value = (err);                                                                                   \
    }                                                                                          \
    }

#define H5_BEFORE_USER_CB_NOCHECK                                                                            \
    {                                                                                                        \
        H5_user_cb_state_t state;                                                                            \
                                                                                                             \
        H5_user_cb_prepare(&state);

#define H5_AFTER_USER_CB_NOCHECK                                                                             \
    H5_user_cb_restore(&state);                                                                              \
    }

#define H5ARG_TRACE0(C, T)                         C, T
#define H5ARG_TRACE1(C, T, A0)                     C, T, #A0, A0
#define H5ARG_TRACE2(C, T, A0, A1)                 C, T, #A0, A0, #A1, A1
#define H5ARG_TRACE3(C, T, A0, A1, A2)             C, T, #A0, A0, #A1, A1, #A2, A2
#define H5ARG_TRACE4(C, T, A0, A1, A2, A3)         C, T, #A0, A0, #A1, A1, #A2, A2, #A3, A3
#define H5ARG_TRACE5(C, T, A0, A1, A2, A3, A4)     C, T, #A0, A0, #A1, A1, #A2, A2, #A3, A3, #A4, A4
#define H5ARG_TRACE6(C, T, A0, A1, A2, A3, A4, A5) C, T, #A0, A0, #A1, A1, #A2, A2, #A3, A3, #A4, A4, #A5, A5
#define H5ARG_TRACE7(C, T, A0, A1, A2, A3, A4, A5, A6)                                                       \
    C, T, #A0, A0, #A1, A1, #A2, A2, #A3, A3, #A4, A4, #A5, A5, #A6, A6
#define H5ARG_TRACE8(C, T, A0, A1, A2, A3, A4, A5, A6, A7)                                                   \
    C, T, #A0, A0, #A1, A1, #A2, A2, #A3, A3, #A4, A4, #A5, A5, #A6, A6, #A7, A7
#define H5ARG_TRACE9(C, T, A0, A1, A2, A3, A4, A5, A6, A7, A8)                                               \
    C, T, #A0, A0, #A1, A1, #A2, A2, #A3, A3, #A4, A4, #A5, A5, #A6, A6, #A7, A7, #A8, A8
#define H5ARG_TRACE10(C, T, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)                                          \
    C, T, #A0, A0, #A1, A1, #A2, A2, #A3, A3, #A4, A4, #A5, A5, #A6, A6, #A7, A7, #A8, A8, #A9, A9
#define H5ARG_TRACE11(C, T, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)                                     \
    C, T, #A0, A0, #A1, A1, #A2, A2, #A3, A3, #A4, A4, #A5, A5, #A6, A6, #A7, A7, #A8, A8, #A9, A9, #A10, A10
#define H5ARG_TRACE12(C, T, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)                                \
    C, T, #A0, A0, #A1, A1, #A2, A2, #A3, A3, #A4, A4, #A5, A5, #A6, A6, #A7, A7, #A8, A8, #A9, A9, #A10,    \
        A10, #A11, A11

struct H5RS_str_t;
H5_DLL double H5_trace(const double *calltime, const char *func, const char *type, ...);
H5_DLL herr_t H5_trace_args(struct H5RS_str_t *rs, const char *type, va_list ap);

extern char H5_lib_vers_info_g[];

#if defined(H5_HAVE_THREADSAFE) || defined(H5_HAVE_CONCURRENCY)
#define H5_HAVE_THREADSAFE_API
#endif

#ifdef H5_HAVE_THREADSAFE_API

#include "H5TSprivate.h"

#if defined(H5_HAVE_PTHREAD_H)

#define H5CANCEL_DECL int oldstate = 0;

#define H5TS_DISABLE_CANCEL                                                                                  \
    do {                                                                                                     \
        pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);                                           \
    } while (0)
#define H5TS_RESTORE_CANCEL                                                                                  \
    do {                                                                                                     \
        pthread_setcancelstate(oldstate, NULL);                                                              \
    } while (0)
#else

#define H5CANCEL_DECL 

#define H5TS_DISABLE_CANCEL                                                                                  \
    do {                                                                                                     \
    } while (0) 
#define H5TS_RESTORE_CANCEL                                                                                  \
    do {                                                                                                     \
    } while (0) 
#endif

#ifdef H5_HAVE_THREADSAFE

#define H5DLFTT_DECL 

#define H5_API_LOCK                                                                                          \
                                                                                   \
    H5TS_api_lock();                                                                                         \
                                                                                                             \
                                \
    H5TS_DISABLE_CANCEL;
#define H5_API_UNLOCK                                                                                        \
                                                                                   \
    H5TS_api_unlock();                                                                                       \
                                                                                                             \
                                                             \
    H5TS_RESTORE_CANCEL;
#else 

#define H5DLFTT_DECL unsigned dlftt = 0;

#define H5_API_LOCK                                                                                          \
                                                                                   \
    H5TS_api_lock(&dlftt);                                                                                   \
                                                                                                             \
                                \
    if (0 == dlftt)                                                                                          \
        H5TS_DISABLE_CANCEL;
#define H5_API_UNLOCK                                                                                        \
    if (0 == dlftt) {                                                                                        \
                                                                                   \
        H5TS_api_unlock();                                                                                   \
                                                                                                             \
                                                             \
        H5TS_RESTORE_CANCEL;                                                                                 \
    }
#endif
#else                 

#define H5CANCEL_DECL 

#define H5DLFTT_DECL  

#define H5_API_LOCK   
#define H5_API_UNLOCK 

#endif 

#define H5_INIT_GLOBAL (H5_libinit_g)
#define H5_TERM_GLOBAL (H5_libterm_g)

#define H5_PACKAGE_INIT_VAR(x)  H5_GLUE(x, _init_g)
#define H5_PACKAGE_INIT_FUNC(x) H5_GLUE(x, __init_package)

#ifdef H5_MY_PKG
#define H5_PKG_INIT_VAR  H5_PACKAGE_INIT_VAR(H5_MY_PKG)
#define H5_PKG_INIT_FUNC H5_PACKAGE_INIT_FUNC(H5_MY_PKG)
#define H5_PACKAGE_YES_INIT(err)                                                                             \
                                                                      \
    if (H5_UNLIKELY(!H5_PKG_INIT_VAR && !H5_TERM_GLOBAL)) {                                                  \
        H5_PKG_INIT_VAR = true;                                                                              \
        if (H5_PKG_INIT_FUNC() < 0) {                                                                        \
            H5_PKG_INIT_VAR = false;                                                                         \
            HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, err, "interface initialization failed");                     \
        }                                                                                                    \
    }
#define H5_PACKAGE_NO_INIT(err)                                                                              \
                                           \
    if (H5_UNLIKELY(!H5_PKG_INIT_VAR && !H5_TERM_GLOBAL))                                                    \
        H5_PKG_INIT_VAR = true;
#define H5_PACKAGE_INIT(pkg_init, err) H5_GLUE3(H5_PACKAGE_, pkg_init, _INIT)(err)
#else 
#define H5_PKG_INIT_VAR (true)
#define H5_PACKAGE_INIT(pkg_init, err)
#endif 

#include "H5CXprivate.h" 

#define H5_IS_PUBLIC(S)                                                                                      \
    ('_' != ((const char *)S)[2]                                           \
     && '_' != ((const char *)S)[3]                                        \
     && !(                                                                             \
          ((const char *)S)[4]                                                         \
          && (isupper((int)S[3]) || isdigit((int)S[3]))                                \
          && '_' == ((const char *)S)[4]                                               \
          ))

#define H5_IS_PRIVATE(S)                                                                                     \
    (((isdigit((int)S[1]) || isupper((int)S[1])) && '_' == S[2] && islower((int)S[3])) ||                    \
     ((isdigit((int)S[2]) || isupper((int)S[2])) && '_' == S[3] && islower((int)S[4])) ||                    \
     ((isdigit((int)S[3]) || isupper((int)S[3])) && '_' == S[4] && islower((int)S[5])))

#define H5_IS_PKG(S)                                                                                         \
    (((isdigit((int)S[1]) || isupper((int)S[1])) && '_' == S[2] && '_' == S[3] && islower((int)S[4])) ||     \
     ((isdigit((int)S[2]) || isupper((int)S[2])) && '_' == S[3] && '_' == S[4] && islower((int)S[5])) ||     \
     ((isdigit((int)S[3]) || isupper((int)S[3])) && '_' == S[4] && '_' == S[5] && islower((int)S[6])))

#ifndef NDEBUG
#define H5_CHECK_FUNCTION_NAME(asrt)                                                                         \
    {                                                                                                        \
        static bool func_check = false;                                                                      \
                                                                                                             \
        if (H5_UNLIKELY(!func_check)) {                                                                      \
                                                                           \
            assert(asrt &&                                                                                   \
                   "Function naming conventions are incorrect (see H5private.h)"                             \
                   "(this is usually due to an incorrect number of underscores in the function name)");      \
                                                                                                             \
                                                                                      \
            func_check = true;                                                                               \
        }                                                                                                    \
    }
#else
#define H5_CHECK_FUNCTION_NAME(asrt)
#endif

#define H5_API_SETUP_ERROR_HANDLING                                                                          \
    bool err_occurred = false;

#define H5_API_SETUP_PUBLIC_API_VARS                                                                         \
    H5CANCEL_DECL                  \
    H5DLFTT_DECL  

#define H5_API_SETUP_INIT_LIBRARY(err)                                                                       \
    do {                                                                                                     \
        if (H5_UNLIKELY(!H5_INIT_GLOBAL && !H5_TERM_GLOBAL)) {                                               \
            if (H5_UNLIKELY(H5_init_library() < 0))                                                          \
                HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, err, "library initialization failed");                   \
        }                                                                                                    \
                                                                 \
        H5_PACKAGE_INIT(H5_MY_PKG_INIT, err)                                                                 \
    } while (0)

#define H5_API_SETUP_PUSH_CONTEXT(err)                                                                       \
                                                                                                          \
    do {                                                                                                     \
        if (H5_UNLIKELY(H5CX_push(&api_ctx) < 0))                                                            \
            HGOTO_ERROR(H5E_FUNC, H5E_CANTSET, err, "can't set API context");                                \
        else                                                                                                 \
            api_ctx_pushed = true;                                                                           \
    } while (0)

#define FUNC_ENTER_API(err)                                                                                  \
    {                                                                                                        \
        {                                                                                                    \
            H5CX_node_t api_ctx        = {{0}, NULL};                                                        \
            bool        api_ctx_pushed = false;                                                              \
                                                                                                             \
            H5_CHECK_FUNCTION_NAME(H5_IS_PUBLIC(__func__));                                                  \
                                                                                                             \
            H5_API_SETUP_PUBLIC_API_VARS                                                                     \
            H5_API_SETUP_ERROR_HANDLING                                                                      \
            H5_API_LOCK                                                                                      \
            H5_API_SETUP_INIT_LIBRARY(err);                                                                  \
            H5_API_SETUP_PUSH_CONTEXT(err);                                                                  \
                                                                                                             \
                                                     \
            H5E_clear_stack();                                                                               \
            {

#define FUNC_ENTER_API_NOCLEAR(err)                                                                          \
    {                                                                                                        \
        {                                                                                                    \
            H5CX_node_t api_ctx        = {{0}, NULL};                                                        \
            bool        api_ctx_pushed = false;                                                              \
                                                                                                             \
            H5_CHECK_FUNCTION_NAME(H5_IS_PUBLIC(__func__));                                                  \
                                                                                                             \
            H5_API_SETUP_PUBLIC_API_VARS                                                                     \
            H5_API_SETUP_ERROR_HANDLING                                                                      \
            H5_API_LOCK                                                                                      \
            H5_API_SETUP_INIT_LIBRARY(err);                                                                  \
            H5_API_SETUP_PUSH_CONTEXT(err);                                                                  \
            {

#define FUNC_ENTER_API_NOINIT                                                                                \
    {                                                                                                        \
        {                                                                                                    \
            {                                                                                                \
                H5_CHECK_FUNCTION_NAME(H5_IS_PUBLIC(__func__));                                              \
                                                                                                             \
                H5_API_SETUP_PUBLIC_API_VARS                                                                 \
                H5_API_SETUP_ERROR_HANDLING                                                                  \
                H5_API_LOCK                                                                                  \
                {

#define FUNC_ENTER_API_NOINIT_NOERR                                                                          \
    {                                                                                                        \
        {                                                                                                    \
            {                                                                                                \
                {                                                                                            \
                    H5_CHECK_FUNCTION_NAME(H5_IS_PUBLIC(__func__));                                          \
                                                                                                             \
                    H5_API_SETUP_PUBLIC_API_VARS                                                             \
                    H5_API_LOCK                                                                              \
                    {

#define FUNC_ENTER_API_NOPUSH(err)                                                                           \
    {                                                                                                        \
        {                                                                                                    \
            {                                                                                                \
                {                                                                                            \
                    {                                                                                        \
                        H5_CHECK_FUNCTION_NAME(H5_IS_PUBLIC(__func__));                                      \
                                                                                                             \
                        H5_API_SETUP_PUBLIC_API_VARS                                                         \
                        H5_API_SETUP_ERROR_HANDLING                                                          \
                        H5_API_LOCK                                                                          \
                        H5_API_SETUP_INIT_LIBRARY(err);                                                      \
                        {

#define FUNC_ENTER_API_NAMECHECK_ONLY                                                                        \
    {                                                                                                        \
        {                                                                                                    \
            {                                                                                                \
                {                                                                                            \
                    {                                                                                        \
                        {                                                                                    \
                            H5_CHECK_FUNCTION_NAME(H5_IS_PUBLIC(__func__));                                  \
                            {

#define FUNC_ENTER_NOAPI_INIT(err)                                                                           \
                                                                 \
    H5_PACKAGE_INIT(H5_MY_PKG_INIT, err)

#define FUNC_ENTER_NOAPI(err)                                                                                \
    {                                                                                                        \
        H5_CHECK_FUNCTION_NAME(H5_IS_PRIVATE(__func__));                                                     \
                                                                                                             \
        H5_API_SETUP_ERROR_HANDLING                                                                          \
        FUNC_ENTER_NOAPI_INIT(err)                                                                           \
        if (H5_LIKELY(H5_PKG_INIT_VAR || !H5_TERM_GLOBAL))                                                   \
        {

#define FUNC_ENTER_NOAPI_NOERR                                                                               \
    {                                                                                                        \
        H5_CHECK_FUNCTION_NAME(H5_IS_PRIVATE(__func__));                                                     \
                                                                                                             \
        FUNC_ENTER_NOAPI_INIT(-)                                                                             \
        if (H5_LIKELY(H5_PKG_INIT_VAR || !H5_TERM_GLOBAL))                                                   \
        {

#define FUNC_ENTER_NOAPI_NOINIT                                                                              \
    {                                                                                                        \
        H5_CHECK_FUNCTION_NAME(H5_IS_PRIVATE(__func__));                                                     \
                                                                                                             \
        H5_API_SETUP_ERROR_HANDLING                                                                          \
        if (H5_LIKELY(H5_PKG_INIT_VAR || !H5_TERM_GLOBAL))                                                   \
        {

#define FUNC_ENTER_NOAPI_NOINIT_NOERR                                                                        \
    {                                                                                                        \
        H5_CHECK_FUNCTION_NAME(H5_IS_PRIVATE(__func__));                                                     \
                                                                                                             \
        if (H5_LIKELY(H5_PKG_INIT_VAR || !H5_TERM_GLOBAL))                                                   \
        {

#define FUNC_ENTER_NOAPI_NAMECHECK_ONLY                                                                      \
    {                                                                                                        \
        H5_CHECK_FUNCTION_NAME(H5_IS_PRIVATE(__func__));

#define FUNC_ENTER_NOAPI_TAG(tag, err)                                                                       \
    {                                                                                                        \
        haddr_t prev_tag = HADDR_UNDEF;                                                                      \
                                                                                                             \
        H5_CHECK_FUNCTION_NAME(H5_IS_PRIVATE(__func__));                                                     \
                                                                                                             \
        H5_API_SETUP_ERROR_HANDLING                                                                          \
                                                                                                             \
        H5AC_tag(tag, &prev_tag);                                                                            \
        FUNC_ENTER_NOAPI_INIT(err)                                                                           \
        if (H5_LIKELY(H5_PKG_INIT_VAR || !H5_TERM_GLOBAL))                                                   \
        {

#define FUNC_ENTER_NOAPI_NOINIT_TAG(tag)                                                                     \
    {                                                                                                        \
        haddr_t prev_tag = HADDR_UNDEF;                                                                      \
                                                                                                             \
        H5_CHECK_FUNCTION_NAME(H5_IS_PRIVATE(__func__));                                                     \
                                                                                                             \
        H5_API_SETUP_ERROR_HANDLING                                                                          \
                                                                                                             \
        H5AC_tag(tag, &prev_tag);                                                                            \
        if (H5_LIKELY(H5_PKG_INIT_VAR || !H5_TERM_GLOBAL))                                                   \
        {

#define FUNC_ENTER_PACKAGE                                                                                   \
    {                                                                                                        \
        H5_CHECK_FUNCTION_NAME(H5_IS_PKG(__func__));                                                         \
                                                                                                             \
        H5_API_SETUP_ERROR_HANDLING                                                                          \
        if (H5_LIKELY(H5_PKG_INIT_VAR || !H5_TERM_GLOBAL))                                                   \
        {

#define FUNC_ENTER_PACKAGE_NOERR                                                                             \
    {                                                                                                        \
        H5_CHECK_FUNCTION_NAME(H5_IS_PKG(__func__));                                                         \
        if (H5_LIKELY(H5_PKG_INIT_VAR || !H5_TERM_GLOBAL))                                                   \
        {

#define FUNC_ENTER_PACKAGE_TAG(tag)                                                                          \
    {                                                                                                        \
        haddr_t prev_tag = HADDR_UNDEF;                                                                      \
                                                                                                             \
        H5_CHECK_FUNCTION_NAME(H5_IS_PKG(__func__));                                                         \
                                                                                                             \
        H5_API_SETUP_ERROR_HANDLING                                                                          \
                                                                                                             \
        H5AC_tag(tag, &prev_tag);                                                                            \
        if (H5_LIKELY(H5_PKG_INIT_VAR || !H5_TERM_GLOBAL))                                                   \
        {

#define FUNC_ENTER_PACKAGE_NAMECHECK_ONLY                                                                    \
    {                                                                                                        \
        H5_CHECK_FUNCTION_NAME(H5_IS_PKG(__func__));

#define FUNC_LEAVE_API(ret_value)                                                                            \
    ;                                                                                                        \
    }                                                                  \
    if (H5_LIKELY(api_ctx_pushed)) {                                                                         \
        (void)H5CX_pop(true);                                                                                \
        api_ctx_pushed = false;                                                                              \
    }                                                                                                        \
    if (H5_UNLIKELY(err_occurred))                                                                           \
        (void)H5E_dump_api_stack();                                                                          \
    H5_API_UNLOCK                                                                                            \
    return (ret_value);                                                                                      \
    }                                                                                                        \
    } 

#define FUNC_LEAVE_API_NOINIT(ret_value)                                                                     \
    ;                                                                                                        \
    }                                                                  \
    if (H5_UNLIKELY(err_occurred))                                                                           \
        (void)H5E_dump_api_stack();                                                                          \
    H5_API_UNLOCK                                                                                            \
    return (ret_value);                                                                                      \
    }                                                                                                        \
    }                                                                                                        \
    } 

#define FUNC_LEAVE_API_NOERR(ret_value)                                                                      \
    ;                                                                                                        \
    }                                                                  \
    H5_API_UNLOCK                                                                                            \
    return (ret_value);                                                                                      \
    }                                                                                                        \
    }                                                                                                        \
    }                                                                                                        \
    } 

#define FUNC_LEAVE_API_NOPUSH(ret_value)                                                                     \
    ;                                                                                                        \
    }                                                                  \
    if (H5_UNLIKELY(err_occurred))                                                                           \
        (void)H5E_dump_api_stack();                                                                          \
    H5_API_UNLOCK                                                                                            \
    return (ret_value);                                                                                      \
    }                                                                                                        \
    }                                                                                                        \
    }                                                                                                        \
    }                                                                                                        \
    } 

#define FUNC_LEAVE_API_NAMECHECK_ONLY(ret_value)                                                             \
    ;                                                                                                        \
    }                                                                  \
    return (ret_value);                                                                                      \
    }                                                                                                        \
    }                                                                                                        \
    }                                                                                                        \
    }                                                                                                        \
    }                                                                                                        \
    } 

#define FUNC_LEAVE_NOAPI(ret_value)                                                                          \
    ;                                                                                                        \
    }                                                                  \
    return (ret_value);                                                                                      \
    } 

#define FUNC_LEAVE_NOAPI_VOID                                                                                \
    ;                                                                                                        \
    }                                                                  \
    return;                                                                                                  \
    } 

#define FUNC_LEAVE_NOAPI_NAMECHECK_ONLY(ret_value)                                                           \
    return (ret_value);                                                                                      \
    } 
#define FUNC_LEAVE_NOAPI_VOID_NAMECHECK_ONLY                                                                 \
    return;                                                                                                  \
    } 

#define FUNC_LEAVE_NOAPI_TAG(ret_value)                                                                      \
    ;                                                                                                        \
    }                                                                  \
    H5AC_tag(prev_tag, NULL);                                                                                \
    return (ret_value);                                                                                      \
    } 

#define H5_PKG_DECLARE_YES_FUNC(pkg) extern herr_t H5_PACKAGE_INIT_FUNC(pkg)(void);
#define H5_PKG_DECLARE_NO_FUNC(pkg)

#define H5_PKG_DECLARE_VAR(pkg)            extern bool H5_PACKAGE_INIT_VAR(pkg);
#define H5_PKG_DECLARE_FUNC(pkg_init, pkg) H5_GLUE3(H5_PKG_DECLARE_, pkg_init, _FUNC)(pkg)

#ifdef H5_MY_PKG
H5_PKG_DECLARE_VAR(H5_MY_PKG)
H5_PKG_DECLARE_FUNC(H5_MY_PKG_INIT, H5_MY_PKG)
#endif

#define H5_BEGIN_TAG(tag)                                                                                    \
    {                                                                                                        \
        haddr_t prv_tag = HADDR_UNDEF;                                                                       \
        H5AC_tag(tag, &prv_tag);

#define H5_END_TAG                                                                                           \
    H5AC_tag(prv_tag, NULL);                                                                                 \
    }

#define HDcompile_assert(e) ((void)sizeof(char[!!(e) ? 1 : -1]))

#include "H5encode.h"

H5_DLL herr_t H5_init_library(void);
H5_DLL void   H5_term_library(void);

H5_DLL int H5A_term_package(void);
H5_DLL int H5A_top_term_package(void);
H5_DLL int H5AC_term_package(void);
H5_DLL int H5CX_term_package(void);
H5_DLL int H5D_term_package(void);
H5_DLL int H5D_top_term_package(void);
H5_DLL int H5E_term_package(void);
H5_DLL int H5ES_term_package(void);
H5_DLL int H5F_term_package(void);
H5_DLL int H5FD_term_package(void);
H5_DLL int H5FL_term_package(void);
H5_DLL int H5FS_term_package(void);
H5_DLL int H5G_term_package(void);
H5_DLL int H5G_top_term_package(void);
H5_DLL int H5I_term_package(void);
H5_DLL int H5L_term_package(void);
H5_DLL int H5M_term_package(void);
H5_DLL int H5M_top_term_package(void);
H5_DLL int H5P_term_package(void);
H5_DLL int H5PL_term_package(void);
H5_DLL int H5R_term_package(void);
H5_DLL int H5R_top_term_package(void);
H5_DLL int H5S_term_package(void);
H5_DLL int H5S_top_term_package(void);
H5_DLL int H5SL_term_package(void);
H5_DLL int H5T_term_package(void);
H5_DLL int H5T_top_term_package(void);
H5_DLL int H5VL_term_package(void);
H5_DLL int H5Z_term_package(void);

H5_DLL uint32_t H5_checksum_fletcher32(const void *data, size_t len);
H5_DLL uint32_t H5_checksum_crc(const void *data, size_t len);
H5_DLL uint32_t H5_checksum_lookup3(const void *data, size_t len, uint32_t initval);
H5_DLL uint32_t H5_checksum_metadata(const void *data, size_t len, uint32_t initval);
H5_DLL uint32_t H5_hash_string(const char *str);

H5_DLL time_t H5_make_time(struct tm *tm);
H5_DLL void   H5_nanosleep(uint64_t nanosec);
H5_DLL double H5_get_time(void);

H5_DLL herr_t H5_build_extpath(const char *name, char **extpath );
H5_DLL herr_t H5_combine_path(const char *path1, const char *path2, char **full_name );
H5_DLL herr_t H5_dirname(const char *path, char **dirname );
H5_DLL herr_t H5_basename(const char *path, char **basename );

H5_DLLVAR int         H5_opterr; 
H5_DLLVAR int         H5_optind; 
H5_DLLVAR const char *H5_optarg; 

enum h5_arg_level {
    no_arg = 0,  
    require_arg, 
    optional_arg 
};

struct h5_long_options {
    const char       *name;     
    enum h5_arg_level has_arg;  
    char              shortval; 
};

H5_DLL int H5_get_option(int argc, const char *const *argv, const char *opt,
                         const struct h5_long_options *l_opt);

#ifdef H5_HAVE_PARALLEL

H5_DLL hsize_t H5_mpi_set_bigio_count(hsize_t new_count);
H5_DLL hsize_t H5_mpi_get_bigio_count(void);
H5_DLL herr_t  H5_mpi_comm_dup(MPI_Comm comm, MPI_Comm *comm_new);
H5_DLL herr_t  H5_mpi_info_dup(MPI_Info info, MPI_Info *info_new);
H5_DLL herr_t  H5_mpi_comm_free(MPI_Comm *comm);
H5_DLL herr_t  H5_mpi_info_free(MPI_Info *info);
H5_DLL herr_t  H5_mpi_comm_cmp(MPI_Comm comm1, MPI_Comm comm2, int *result);
H5_DLL herr_t  H5_mpi_info_cmp(MPI_Info info1, MPI_Info info2, int *result);
H5_DLL herr_t  H5_mpio_create_large_type(hsize_t num_elements, MPI_Aint stride_bytes, MPI_Datatype old_type,
                                         MPI_Datatype *new_type);
H5_DLL herr_t  H5_mpio_gatherv_alloc(void *send_buf, int send_count, MPI_Datatype send_type,
                                     const int recv_counts[], const int displacements[],
                                     MPI_Datatype recv_type, bool allgather, int root, MPI_Comm comm,
                                     int mpi_rank, int mpi_size, void **out_buf, size_t *out_buf_num_entries);
H5_DLL herr_t  H5_mpio_gatherv_alloc_simple(void *send_buf, int send_count, MPI_Datatype send_type,
                                            MPI_Datatype recv_type, bool allgather, int root, MPI_Comm comm,
                                            int mpi_rank, int mpi_size, void **out_buf,
                                            size_t *out_buf_num_entries);
H5_DLL herr_t  H5_mpio_get_file_sync_required(MPI_File fh, bool *file_sync_required);
#endif 

H5_DLL herr_t H5_buffer_dump(FILE *stream, int indent, const uint8_t *buf, const uint8_t *marker,
                             size_t buf_offset, size_t buf_size);

H5_DLL herr_t H5_user_cb_prepare(H5_user_cb_state_t *state);
H5_DLL herr_t H5_user_cb_restore(const H5_user_cb_state_t *state);
#endif 
