#ifndef _TYPEDEFS_H_
#define _TYPEDEFS_H_

/******** Definition of items with uniquely size **********
(c) 1997-2014 Jaroslav Fojtik
   if you don't use below mentionted compiler, please correct this items
   for your compiler and send me your correction to:
			fojtik@penguin.cz or JaFojtik@seznam.cz

List of supported types:

   Type  Alternate  Size & Description
   -----+---------+------+---------------------
   __u8   BYTE     1 byte  =  8 bit
   __s8   SBYTE    1 byte  =  8 bit signed
   __u16  WORD     2 bytes = 16 bit
   __s16  SWORD    2 bytes = 16 bit signed
   __u32  DWORD    4 bytes = 32 bit
   __s32  SDWORD   4 bytes = 32 bit signed

***************************************************************/


#ifdef __cplusplus
extern "C" {
#endif


#ifdef __BORLANDC__
 #define NATIVE_ACCESS
 #ifndef LO_ENDIAN
  #define LO_ENDIAN
 #endif
 #if defined(__OS2__) || defined(__WIN32__)
   #define __u16   unsigned short int
   #define __s16   signed short int
 #else
   #define __u16   unsigned int
   #define __s16   signed int
 #endif
 #define __u32   unsigned long int
 #define __s32   signed long int
#else  /* __BORLANDC__ */

#if defined(__EGC__) || defined(__GNUC__)
 #define NATIVE_ACCESS
 #ifdef __MINGW32__
  #include <basetsd.h>
 #endif

 #if (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__) || defined(__DJGPP__) || defined(__MINGW32__)
  #ifndef LO_ENDIAN
   #define LO_ENDIAN
  #endif
 #endif

 typedef int __s8 __attribute__((mode(QI)));
 typedef unsigned int __u8 __attribute__((mode(QI)));
 typedef int __s16 __attribute__((mode(HI)));
 typedef unsigned int __u16 __attribute__((mode(HI)));
 typedef int __s32 __attribute__((mode(SI)));
 #ifndef __MINGW32__
  typedef unsigned int __u32 __attribute__((mode(SI)));
  #define __u32 __u32
 #endif
 typedef int __s64 __attribute__((mode(DI)));
 typedef unsigned int __u64 __attribute__((mode(DI)));
 #define __u8 __u8
 #define __u16 __u16
 #define __u64 __u64

 #if __GNUC__>4 || (__GNUC__==4 && __GNUC_MINOR__>=3)
  #define LD_UINT32_SWAP(ptr)  __builtin_bswap32((__u32)(*(UINT32*)(__u8*)(ptr)))
  #define LD_UINT64_SWAP(ptr)  __builtin_bswap64((__u64)(*(unsigned int64_t*)(__u8*)(ptr)))
 #endif

#else  /* __EGC__ || __GNUC__ */

#ifdef __WATCOMC__
 #define NATIVE_ACCESS
 #ifdef __386__
  #define __u16   unsigned short int
  #define __s16   signed short int
  #define __u32   unsigned int
  #define __s32   signed int
 #else
  #define __u16   unsigned int
  #define __s16   signed int
  #define __u32   unsigned long int
  #define __s32   signed long int
 #endif
#else /*__WATCOMC__*/

#ifdef __HPUXC__
 #define __u16	unsigned short int
 #define __s16	signed short int
 #define __u32	unsigned int
 #define __s32	signed int
#else

#if defined(__IAR_SYSTEMS_ICC__) || defined(__ARMCC_VERSION)
 #ifndef LO_ENDIAN
  #define LO_ENDIAN
 #endif

 #ifdef __IAR_SYSTEMS_ICC__	/* IAR */
  #ifdef NATIVE_ACCESS
   #undef NATIVE_ACCESS
  #endif
 #else				/* Keil */
  #ifndef NATIVE_ACCESS
   #define NATIVE_ACCESS
   #define PACKED_PTR __packed
  #endif
 #endif

 #define  __s16 signed short
 #define  __u16 unsigned short
 #define  __s32 signed int
 #define  __u32 unsigned int
 #define  __s64 long long
 #define  __u64 unsigned long long
#else

#ifdef _MSC_VER

 #ifndef NATIVE_ACCESS
  #define NATIVE_ACCESS
 #endif
 #ifndef LO_ENDIAN
  #define LO_ENDIAN
 #endif

 #if _MSC_VER > 1200
  #define  __s64 __int64
  #define  __u64 unsigned __int64
 #endif

 #define LD_UINT16_SWAP(ptr)  _byteswap_ushort((__u16)(*(__u16*)(__u8*)(ptr)))
 #define LD_UINT32_SWAP(ptr)  _byteswap_ulong((__u32)(*(UINT32*)(__u8*)(ptr)))
 #define LD_UINT64_SWAP(ptr)  _byteswap_uint64((unsigned __int64)(*(unsigned __int64*)(__u8*)(ptr)))

 #define ST_UINT16_SWAP(ptr,val)  *(__u16*)(__u8*)(ptr)=_byteswap_ushort((__u16)(val))
 #define ST_UINT32_SWAP(ptr,val)  *(UINT32*)(__u8*)(ptr)=_byteswap_ulong((__u32)(val))
 #define ST_UINT64_SWAP(ptr,val)  *(UINT64*)(__u8*)(ptr)=_byteswap_uint64((__u64)(val))

/* Here you may include your definition for other C */
#endif
#endif
#endif
#endif
#endif
#endif


#ifndef PACKED_PTR
 #define PACKED_PTR
#endif


#ifndef __u8
 #define __u8    unsigned char
 #define __s8    signed char
#endif
#ifndef __u16
 #define __u16   unsigned short
 #define __s16   signed short
#endif
#ifndef __u32
 #define __u32   unsigned long int
 #define __s32   signed long int
#endif

/* Alternative naming. */
#ifndef BYTE
 #define BYTE    __u8
 #define SBYTE   __s8
 #define WORD    __u16
 #define SWORD   __s16
 #define SDWORD  __s32
 #ifdef __u64
  #define QWORD  __u64
  #define SQWORD __s64
 #endif
 // #ifndef __MINGW32__
  #define DWORD   __u32
 // #endif
#endif


/* Alternative #2 naming. */
#ifndef INT8
 typedef __s8	INT8;
 typedef __u8	UINT8;
 typedef __s16	INT16;
 typedef __u16	UINT16;

 #if !defined(_MSC_VER) && !defined(__MINGW32__)  && !defined(INT32) 
  /* typedef __s32  INT32; */
  #define INT32 __s32
  typedef __u32  UINT32;
 #endif

 #ifdef __u64
  typedef __s64	INT64;
  typedef __u64	UINT64;
 #endif
#endif



#define LD_UINT16_CPU(ptr)	(__u16)(*(PACKED_PTR __u16*)(__u8*)(ptr))
#define LD_UINT32_CPU(ptr)	(__u32)(*(PACKED_PTR UINT32*)(__u8*)(ptr))
#ifdef __u64
 #define LD_UINT64_CPU(ptr)	(__u64)(*(PACKED_PTR UINT64*)(__u8*)(ptr))
#endif

#define ST_UINT16_CPU(ptr,val)	*(PACKED_PTR __u16*)(__u8*)(ptr)=(__u16)(val)
#define ST_UINT32_CPU(ptr,val)	*(PACKED_PTR UINT32*)(__u8*)(ptr)=(__u32)(val)
#ifdef __u64
 #define ST_UINT64_CPU(ptr,val)	*(PACKED_PTR UINT64*)(__u8*)(ptr)=(__u64)(val)
#endif


/* Prototypes for floats and doubles. */
double LD_DOUBLE_SWAP(const void *b);
void ST_DOUBLE_SWAP(void *b, double d);
float LD_FLOAT_SWAP(const void *b);
void ST_FLOAT_SWAP(void *b, float f);


/* #undef NATIVE_ACCESS */


#ifdef NATIVE_ACCESS  /* Enable word access to structures. */
 #ifdef LO_ENDIAN
  #define LD_UINT16_LO(ptr)	LD_UINT16_CPU(ptr)
  #define LD_UINT32_LO(ptr)	LD_UINT32_CPU(ptr)
  #define ST_UINT16_LO(ptr,val)	ST_UINT16_CPU(ptr,val)
  #define ST_UINT32_LO(ptr,val)	ST_UINT32_CPU(ptr,val)
  #ifdef __u64
   #define LD_UINT64_LO(ptr)	LD_UINT64_CPU(ptr)
   #define ST_UINT64_LO(ptr,val) ST_UINT64_CPU(ptr,val)
  #endif
  #ifdef LD_UINT16_SWAP
   #define LD_UINT16_HI(ptr)	LD_UINT16_SWAP(ptr)
  #endif
  #ifdef LD_UINT32_SWAP
   #define LD_UINT32_HI(ptr)	LD_UINT32_SWAP(ptr)
  #endif
  #ifdef __u64
   #ifdef LD_UINT64_SWAP
    #define LD_UINT64_HI(ptr)	LD_UINT64_SWAP(ptr)
   #endif
   #ifdef ST_UINT64_SWAP
    #define ST_UINT64_HI(ptr,val) ST_UINT64_SWAP(ptr,val)
   #endif
  #endif

  #define LD_FLOAT_HI(ptr)	LD_FLOAT_SWAP(ptr)
  #define ST_FLOAT_HI(ptr,val)	ST_FLOAT_SWAP(ptr,val)
  #define LD_DOUBLE_HI(ptr)	LD_DOUBLE_SWAP(ptr)
  #define ST_DOUBLE_HI(ptr,val)	ST_DOUBLE_SWAP(ptr,val)
 #endif
#endif


/* Safe replacements for non native access. */
#ifndef LD_UINT16_LO
 #define LD_UINT16_LO(ptr)	(__u16)(((__u16)*(__u8*)((ptr)+1)<<8)|(__u16)*(__u8*)(ptr))
#endif
#ifndef LD_UINT32_LO
 #define LD_UINT32_LO(ptr)	(__u32)(((__u32)*(__u8*)((ptr)+3)<<24)|((__u32)*(__u8*)((ptr)+2)<<16)|((__u16)*(__u8*)((ptr)+1)<<8)|*(__u8*)(ptr))
#endif
#ifndef ST_UINT16_LO
 #define ST_UINT16_LO(ptr,val)	*(__u8*)(ptr)=(__u8)(val); *(__u8*)((ptr)+1)=(__u8)((__u16)(val)>>8)
#endif
#ifndef ST_UINT32_LO
 #define ST_UINT32_LO(ptr,val)	*(__u8*)(ptr)=(__u8)(val); *(__u8*)((ptr)+1)=(__u8)((__u16)(val)>>8); *(__u8*)((ptr)+2)=(__u8)((__u32)(val)>>16); *(__u8*)((ptr)+3)=(__u8)((__u32)(val)>>24)
#endif

#ifdef __u64
 #ifndef LD_UINT64_LO
  #define LD_UINT64_LO(ptr)	(__u64)((((__u64)*(__u8*)((ptr)+7)<<56) | (((__u64)*(__u8*)((ptr)+6)<<48) | (((__u64)*(__u8*)((ptr)+5)<<40) | (((__u64)*(__u8*)((ptr)+4)<<32) | ((__u32)*(__u8*)((ptr)+3)<<24)|((__u32)*(__u8*)((ptr)+2)<<16) | ((__u16)*(__u8*)((ptr)+1)<<8) | *(__u8*)(ptr))
 #endif
 #ifndef ST_UINT64_LO
  #define ST_UINT64_LO(ptr,val)	*(__u8*)(ptr)=(__u8)(val); *(__u8*)((ptr)+1)=(__u8)((UINT16)(val)>>8); *(__u8*)((ptr)+2)=(__u8)((__u32)(val)>>16); *(__u8*)((ptr)+3)=(__u8)((__u32)(val)>>24); *(__u8*)((ptr)+4)=(__u8)((__u64)(val)>>32); *(__u8*)((ptr)+5)=(__u8)((__u64)(val)>>40); *(__u8*)((ptr)+6)=(__u8)((__u64)(val)>>48); *(__u8*)((ptr)+7)=(__u8)((__u64)(val)>>56)
 #endif
#endif



#ifndef LD_UINT16_HI
#define LD_UINT16_HI(ptr)	(__u16)(((__u16)*(__u8*)((ptr))<<8)|(__u16)*((__u8*)(ptr)+1))
#endif
#ifndef LD_UINT32_HI
#define LD_UINT32_HI(ptr)	(__u32)(((__u32)*(__u8*)((ptr))<<24)|((__u32)*(__u8*)((ptr)+1)<<16)|((__u16)*(__u8*)((ptr)+2)<<8)|*((__u8*)(ptr)+3))
#endif
#ifndef ST_UINT16_HI
#define ST_UINT16_HI(ptr,val)	*((__u8*)(ptr)+1)=(__u8)(val); *(__u8*)((ptr))=(__u8)((__u16)(val)>>8)
#endif
#ifndef ST_UINT32_HI
#define ST_UINT32_HI(ptr,val)	*((__u8*)(ptr)+3)=(__u8)(val); *(__u8*)((ptr)+2)=(__u8)((__u16)(val)>>8); *(__u8*)((ptr)+1)=(__u8)((__u32)(val)>>16); *(__u8*)((ptr))=(__u8)((__u32)(val)>>24)
#endif

#ifdef __u64
 #ifndef LD_UINT64_HI
  #define LD_UINT64_HI(ptr)	(__u64)( ((__u64)*(__u8*)(ptr)<<56) | ((__u64)*(__u8*)((ptr)+1)<<48) | ((__u64)*(__u8*)((ptr)+2)<<40) | ((__u64)*(__u8*)((ptr)+3)<<32) | ((__u32)*(__u8*)((ptr)+4)<<24)|((__u32)*(__u8*)((ptr)+5)<<16) | ((__u16)*(__u8*)((ptr)+6)<<8) | *(__u8*)((ptr)+7) )
 #endif
 #ifndef ST_UINT64_HI
  #define ST_UINT64_HI(ptr,val)	*((__u8*)(ptr)+7)=(__u8)(val); *((__u8*)(ptr)+6)=(__u8)((__u16)(val)>>8); *(__u8*)((ptr)+5)=(__u8)((__u32)(val)>>16); *(__u8*)((ptr)+4)=(__u8)((__u32)(val)>>24); *(__u8*)((ptr)+3)=(__u8)((__u64)(val)>>32); *(__u8*)((ptr)+2)=(__u8)((__u64)(val)>>40); *(__u8*)((ptr)+1)=(__u8)((__u64)(val)>>48); *(__u8*)((ptr))=(__u8)((__u64)(val)>>56)
 #endif
#endif


/* Use byte-by-byte access to structures */
#define LD_UINT16(ptr)		LD_UINT16_LO(ptr)
#define LD_UINT32(ptr)		LD_UINT32_LO(ptr)
#define ST_UINT16(ptr,val)	ST_UINT16_LO(ptr,val)
#define ST_UINT32(ptr,val)	ST_UINT32_LO(ptr,val)
#ifdef __u64
#define LD_UINT64(ptr)		LD_UINT64_LO(ptr)
#define ST_UINT64(ptr,val)	ST_UINT64_LO(ptr,val)
#endif


#ifdef __cplusplus
 }
#endif

#endif  		/* End of Header Typedefs.h */
