/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * 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.                                                        *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#if !(defined H5T_FRIEND || defined H5T_MODULE)
#error "Do not include this file outside the H5T package!"
#endif

#ifndef H5Tpkg_H
#define H5Tpkg_H

#ifdef NDEBUG
#undef H5T_DEBUG
#endif

#include "H5Tprivate.h"

#include "H5Fprivate.h"  
#include "H5FLprivate.h" 
#include "H5Oprivate.h"  
#include "H5VLprivate.h" 

#include "H5Spublic.h" 

#define H5T_IS_COMPOSITE(t)                                                                                  \
    ((t) == H5T_COMPOUND || (t) == H5T_ENUM || (t) == H5T_VLEN || (t) == H5T_ARRAY ||                        \
     (t) == H5T_REFERENCE || (t) == H5T_COMPLEX)

#define H5T_IS_FIXED_STRING(dt) (H5T_STRING == (dt)->type)

#define H5T_IS_VL_STRING(dt) (H5T_VLEN == (dt)->type && H5T_VLEN_STRING == (dt)->u.vlen.type)

#define H5T_IS_STRING(dt) (H5T_IS_FIXED_STRING(dt) || H5T_IS_VL_STRING(dt))

#define H5T_IS_ATOMIC(dt) (!(H5T_IS_COMPOSITE((dt)->type) || (dt)->type == H5T_OPAQUE))

#define H5T_GET_CLASS(shared, internal)                                                                      \
    ((internal) ? (shared)->type : (H5T_IS_VL_STRING(shared) ? H5T_STRING : (shared)->type))

#define H5O_DTYPE_VERSION_1 1

#define H5O_DTYPE_VERSION_2 2

#define H5O_DTYPE_VERSION_3 3

#define H5O_DTYPE_VERSION_4 4

#define H5O_DTYPE_VERSION_5 5

#define H5O_DTYPE_VERSION_LATEST H5O_DTYPE_VERSION_5

#define H5T_VISIT_COMPOSITE_FIRST                                                                            \
    0x01                              
#define H5T_VISIT_COMPOSITE_LAST 0x02 
                                      
#define H5T_VISIT_SIMPLE 0x04         

#if (H5_WANT_DATA_ACCURACY && defined(H5_LLONG_TO_LDOUBLE_CORRECT)) || (!H5_WANT_DATA_ACCURACY)
#define H5T_CONV_INTERNAL_LLONG_LDOUBLE 1
#endif

#if (H5_WANT_DATA_ACCURACY && defined(H5_LLONG_TO_LDOUBLE_CORRECT)) || (!H5_WANT_DATA_ACCURACY)
#define H5T_CONV_INTERNAL_ULLONG_LDOUBLE 1
#endif

#if (H5_WANT_DATA_ACCURACY && defined(H5_LDOUBLE_TO_LLONG_ACCURATE)) || (!H5_WANT_DATA_ACCURACY)
#define H5T_CONV_INTERNAL_LDOUBLE_LLONG 1
#endif

#if (H5_WANT_DATA_ACCURACY && defined(H5_LDOUBLE_TO_LLONG_ACCURATE)) || (!H5_WANT_DATA_ACCURACY)
#define H5T_CONV_INTERNAL_LDOUBLE_ULLONG 1
#endif

#ifdef H5_HAVE__FLOAT16
#if (H5_WANT_DATA_ACCURACY && defined(H5_LDOUBLE_TO_FLOAT16_CORRECT)) || (!H5_WANT_DATA_ACCURACY)
#define H5T_CONV_INTERNAL_LDOUBLE_FLOAT16 1
#endif
#endif

typedef herr_t (*H5T_ref_isnullfunc_t)(const H5VL_object_t *file, const void *src_buf, bool *isnull);
typedef herr_t (*H5T_ref_setnullfunc_t)(H5VL_object_t *file, void *dst_buf, void *bg_buf);
typedef size_t (*H5T_ref_getsizefunc_t)(H5VL_object_t *src_file, const void *src_buf, size_t src_size,
                                        H5VL_object_t *dst_file, bool *dst_copy);
typedef herr_t (*H5T_ref_readfunc_t)(H5VL_object_t *src_file, const void *src_buf, size_t src_size,
                                     H5VL_object_t *dst_file, void *dst_buf, size_t dst_size);
typedef herr_t (*H5T_ref_writefunc_t)(H5VL_object_t *src_file, const void *src_buf, size_t src_size,
                                      H5R_type_t src_type, H5VL_object_t *dst_file, void *dst_buf,
                                      size_t dst_size, void *bg_buf);

typedef struct H5T_ref_class_t {
    H5T_ref_isnullfunc_t  isnull;  
    H5T_ref_setnullfunc_t setnull; 
    H5T_ref_getsizefunc_t getsize; 
    H5T_ref_readfunc_t    read;    
    H5T_ref_writefunc_t   write;   
} H5T_ref_class_t;

typedef struct H5T_atomic_t {
    H5T_order_t order;   
    size_t      prec;    
    size_t      offset;  
    H5T_pad_t   lsb_pad; 
    H5T_pad_t   msb_pad; 
    union {
        struct {
            H5T_sign_t sign; 
        } i;                 

        struct {
            size_t     sign;  
            size_t     epos;  
            size_t     esize; 
            uint64_t   ebias; 
            size_t     mpos;  
            size_t     msize; 
            H5T_norm_t norm;  
            H5T_pad_t  pad;   
        } f;                  

        struct {
            H5T_cset_t cset; 
            H5T_str_t  pad;  
        } s;                 

        struct {
            H5R_type_t             rtype;   
            unsigned               version; 
            bool                   opaque;  
            H5T_loc_t              loc;     
            H5VL_object_t         *file;    
            const H5T_ref_class_t *cls;     
        } r;                                
    } u;
} H5T_atomic_t;

typedef enum H5T_sort_t {
    H5T_SORT_NONE  = 0, 
    H5T_SORT_NAME  = 1, 
    H5T_SORT_VALUE = 2  
} H5T_sort_t;

typedef struct H5T_cmemb_t {
    char         *name;   
    size_t        offset; 
    size_t        size;   
    struct H5T_t *type;   
} H5T_cmemb_t;

typedef struct H5T_compnd_t {
    unsigned     nalloc;    
    unsigned     nmembs;    
    H5T_sort_t   sorted;    
    bool         packed;    
    H5T_cmemb_t *memb;      
    size_t       memb_size; 
} H5T_compnd_t;

typedef struct H5T_enum_t {
    unsigned   nalloc; 
    unsigned   nmembs; 
    H5T_sort_t sorted; 
    void      *value;  
    char     **name;   
} H5T_enum_t;

typedef enum {
    H5T_VLEN_BADTYPE  = -1, 
    H5T_VLEN_SEQUENCE = 0,  
    H5T_VLEN_STRING,        
    H5T_VLEN_MAXTYPE        
} H5T_vlen_type_t;

typedef herr_t (*H5T_vlen_getlen_func_t)(H5VL_object_t *file, const void *vl_addr, size_t *len);
typedef void *(*H5T_vlen_getptr_func_t)(void *vl_addr);
typedef herr_t (*H5T_vlen_isnull_func_t)(const H5VL_object_t *file, void *vl_addr, bool *isnull);
typedef herr_t (*H5T_vlen_setnull_func_t)(H5VL_object_t *file, void *_vl, void *_bg);
typedef herr_t (*H5T_vlen_read_func_t)(H5VL_object_t *file, void *_vl, void *buf, size_t len);
typedef herr_t (*H5T_vlen_write_func_t)(H5VL_object_t *file, const H5T_vlen_alloc_info_t *vl_alloc_info,
                                        void *_vl, void *buf, void *_bg, size_t seq_len, size_t base_size);
typedef herr_t (*H5T_vlen_delete_func_t)(H5VL_object_t *file, void *_vl);

typedef struct H5T_vlen_class_t {
    H5T_vlen_getlen_func_t  getlen;  
    H5T_vlen_getptr_func_t  getptr;  
    H5T_vlen_isnull_func_t  isnull;  
    H5T_vlen_setnull_func_t setnull; 
    H5T_vlen_read_func_t    read;    
    H5T_vlen_write_func_t   write;   
    H5T_vlen_delete_func_t  del;     
} H5T_vlen_class_t;

typedef struct H5T_vlen_t {
    H5T_vlen_type_t type;         
    H5T_loc_t       loc;          
    H5T_cset_t      cset;         
    H5T_str_t       pad;          
    H5VL_object_t          *file; 
    const H5T_vlen_class_t *cls;  
} H5T_vlen_t;

typedef struct H5T_opaque_t {
    char *tag; 
} H5T_opaque_t;

typedef struct H5T_array_t {
    size_t   nelem;             
    unsigned ndims;             
    size_t   dim[H5S_MAX_RANK]; 
} H5T_array_t;

typedef enum H5T_complex_form_t {
    H5T_COMPLEX_RECTANGULAR,
    H5T_COMPLEX_POLAR,
    H5T_COMPLEX_EXPONENTIAL,
} H5T_complex_form_t;

typedef struct H5T_complex_t {
    H5T_complex_form_t form; 
} H5T_complex_t;

typedef enum H5T_state_t {
    H5T_STATE_TRANSIENT, 
    H5T_STATE_RDONLY,    
    H5T_STATE_IMMUTABLE, 
    H5T_STATE_NAMED,     
    H5T_STATE_OPEN       
} H5T_state_t;

typedef struct H5T_shared_t {
    hsize_t     fo_count; 
    H5T_state_t state;    
    H5T_class_t type;     
    size_t      size;     
    unsigned    version;  
    bool force_conv; 
    struct H5T_t  *parent;        
    H5VL_object_t *owned_vol_obj; 
    union {
        H5T_atomic_t  atomic; 
        H5T_compnd_t  compnd; 
        H5T_enum_t    enumer; 
        H5T_vlen_t    vlen;   
        H5T_opaque_t  opaque; 
        H5T_array_t   array;  
        H5T_complex_t cplx;   
    } u;
} H5T_shared_t;

struct H5T_t {
    H5O_shared_t sh_loc; 

    H5T_shared_t  *shared;  
    H5O_loc_t      oloc;    
    H5G_name_t     path;    
    H5VL_object_t *vol_obj; 
};

typedef enum H5T_sdir_t {
    H5T_BIT_LSB, 
    H5T_BIT_MSB  
} H5T_sdir_t;

typedef struct {
    H5T_t *dt;      
    hid_t  tcpl_id; 
} H5T_obj_create_t;

typedef herr_t (*H5T_operator_t)(H5T_t *dt, void *op_data );

H5_DLLVAR const unsigned H5O_dtype_ver_bounds[H5F_LIBVER_NBOUNDS + 1];

H5_DLLVAR size_t H5T_POINTER_ALIGN_g;
H5_DLLVAR size_t H5T_HVL_ALIGN_g;
H5_DLLVAR size_t H5T_HOBJREF_ALIGN_g;
H5_DLLVAR size_t H5T_HDSETREGREF_ALIGN_g;
H5_DLLVAR size_t H5T_REF_ALIGN_g;

H5_DLLVAR size_t H5T_NATIVE_SCHAR_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_UCHAR_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_SHORT_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_USHORT_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_INT_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_UINT_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_LONG_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_ULONG_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_LLONG_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_ULLONG_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_FLOAT16_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_FLOAT_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_DOUBLE_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_LDOUBLE_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_FLOAT_COMPLEX_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_DOUBLE_COMPLEX_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_LDOUBLE_COMPLEX_ALIGN_g;

H5_DLLVAR size_t H5T_NATIVE_INT8_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_UINT8_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_INT_LEAST8_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_UINT_LEAST8_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_INT_FAST8_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_UINT_FAST8_ALIGN_g;

H5_DLLVAR size_t H5T_NATIVE_INT16_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_UINT16_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_INT_LEAST16_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_UINT_LEAST16_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_INT_FAST16_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_UINT_FAST16_ALIGN_g;

H5_DLLVAR size_t H5T_NATIVE_INT32_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_UINT32_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_INT_LEAST32_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_UINT_LEAST32_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_INT_FAST32_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_UINT_FAST32_ALIGN_g;

H5_DLLVAR size_t H5T_NATIVE_INT64_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_UINT64_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_INT_LEAST64_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_UINT_LEAST64_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_INT_FAST64_ALIGN_g;
H5_DLLVAR size_t H5T_NATIVE_UINT_FAST64_ALIGN_g;

#ifdef H5_HAVE__FLOAT16
H5_DLLVAR H5__Float16 H5T_NATIVE_FLOAT16_POS_INF_g;
H5_DLLVAR H5__Float16 H5T_NATIVE_FLOAT16_NEG_INF_g;
#endif
H5_DLLVAR float       H5T_NATIVE_FLOAT_POS_INF_g;
H5_DLLVAR float       H5T_NATIVE_FLOAT_NEG_INF_g;
H5_DLLVAR double      H5T_NATIVE_DOUBLE_POS_INF_g;
H5_DLLVAR double      H5T_NATIVE_DOUBLE_NEG_INF_g;
H5_DLLVAR long double H5T_NATIVE_LDOUBLE_POS_INF_g;
H5_DLLVAR long double H5T_NATIVE_LDOUBLE_NEG_INF_g;
#ifdef H5_HAVE_COMPLEX_NUMBERS
H5_DLLVAR H5_float_complex   H5T_NATIVE_FLOAT_COMPLEX_POS_INF_g;
H5_DLLVAR H5_float_complex   H5T_NATIVE_FLOAT_COMPLEX_NEG_INF_g;
H5_DLLVAR H5_double_complex  H5T_NATIVE_DOUBLE_COMPLEX_POS_INF_g;
H5_DLLVAR H5_double_complex  H5T_NATIVE_DOUBLE_COMPLEX_NEG_INF_g;
H5_DLLVAR H5_ldouble_complex H5T_NATIVE_LDOUBLE_COMPLEX_POS_INF_g;
H5_DLLVAR H5_ldouble_complex H5T_NATIVE_LDOUBLE_COMPLEX_NEG_INF_g;
#endif

H5FL_EXTERN(H5T_t);
H5FL_EXTERN(H5T_shared_t);

H5_DLL herr_t H5T__init_native_float_types(void);
H5_DLL herr_t H5T__init_native_internal(void);
#ifdef H5_HAVE_COMPLEX_NUMBERS
H5_DLL herr_t H5T__init_native_complex_types(void);
#endif
H5_DLL H5T_t *H5T__create(H5T_class_t type, size_t size);
H5_DLL H5T_t *H5T__alloc(void);
H5_DLL herr_t H5T__free(H5T_t *dt);
H5_DLL herr_t H5T__visit(H5T_t *dt, unsigned visit_flags, H5T_operator_t op, void *op_value);
H5_DLL herr_t H5T__upgrade_version(H5T_t *dt, unsigned new_version);

H5_DLL herr_t H5T__commit_anon(H5F_t *file, H5T_t *type, hid_t tcpl_id);
H5_DLL herr_t H5T__commit(H5F_t *file, H5T_t *type, hid_t tcpl_id);
H5_DLL herr_t H5T__commit_named(const H5G_loc_t *loc, const char *name, H5T_t *dt, hid_t lcpl_id,
                                hid_t tcpl_id);
H5_DLL H5T_t *H5T__open_name(const H5G_loc_t *loc, const char *name);
H5_DLL hid_t  H5T__get_create_plist(const H5T_t *type);

H5_DLL void     H5T__bit_copy(uint8_t *dst, size_t dst_offset, const uint8_t *src, size_t src_offset,
                              size_t size);
H5_DLL herr_t   H5T__bit_shift(uint8_t *buf, ssize_t shift_dist, size_t offset, size_t size);
H5_DLL void     H5T__bit_set(uint8_t *buf, size_t offset, size_t size, bool value);
H5_DLL uint64_t H5T__bit_get_d(const uint8_t *buf, size_t offset, size_t size);
H5_DLL void     H5T__bit_set_d(uint8_t *buf, size_t offset, size_t size, uint64_t val);
H5_DLL ssize_t  H5T__bit_find(const uint8_t *buf, size_t offset, size_t size, H5T_sdir_t direction,
                              bool value);
H5_DLL bool     H5T__bit_inc(uint8_t *buf, size_t start, size_t size);
H5_DLL bool     H5T__bit_dec(uint8_t *buf, size_t start, size_t size);
H5_DLL void     H5T__bit_neg(uint8_t *buf, size_t start, size_t size);

H5_DLL H5T_t *H5T__vlen_create(const H5T_t *base);
H5_DLL herr_t H5T__vlen_reclaim(void *elem, const H5T_t *dt, H5T_vlen_alloc_info_t *alloc_info);
H5_DLL htri_t H5T__vlen_set_loc(H5T_t *dt, H5VL_object_t *file, H5T_loc_t loc);

H5_DLL H5T_t *H5T__array_create(H5T_t *base, unsigned ndims, const hsize_t dim[]);
H5_DLL int    H5T__get_array_ndims(const H5T_t *dt);
H5_DLL int    H5T__get_array_dims(const H5T_t *dt, hsize_t dims[]);

H5_DLL herr_t H5T__ref_reclaim(void *elem, const H5T_t *dt);
H5_DLL htri_t H5T__ref_set_loc(H5T_t *dt, H5VL_object_t *file, H5T_loc_t loc);

H5_DLL herr_t H5T__insert(H5T_t *parent, const char *name, size_t offset, const H5T_t *member);
H5_DLL size_t H5T__get_member_size(const H5T_t *dt, unsigned membno);
H5_DLL void   H5T__update_packed(const H5T_t *dt);

H5_DLL H5T_t *H5T__enum_create(const H5T_t *parent);
H5_DLL herr_t H5T__enum_insert(const H5T_t *dt, const char *name, const void *value);
H5_DLL herr_t H5T__get_member_value(const H5T_t *dt, unsigned membno, void *value);

H5_DLL char  *H5T__get_member_name(H5T_t const *dt, unsigned membno) H5_ATTR_MALLOC;
H5_DLL herr_t H5T__sort_value(const H5T_t *dt, int *map);
H5_DLL herr_t H5T__sort_name(const H5T_t *dt, int *map);

H5_DLL H5T_t *H5T__complex_create(const H5T_t *base);

#endif 
