// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.

#ifndef tools_typedefs
#define tools_typedefs

// Similar to AIDA/v3r3p0/Types.h

//NOTE : we avoid to have std includes here to be sure
//       that in the below ifdef things come only from the compiler.

//NOTE : if adding new platform here, look at ./s2int64 too.

namespace tools {

#ifdef _MSC_VER

typedef int int32;
typedef __int64 int64;
inline const char* int32_format() {static const char s_v[] = "%d";return s_v;}
inline const char* int64_format() {static const char s_v[] = "%ld";return s_v;}

typedef unsigned int uint32;
typedef unsigned __int64 uint64;
inline const char* uint32_format() {static const char s_v[] = "%u";return s_v;}
inline const char* uint64_format() {static const char s_v[] = "%lu";return s_v;}

#ifdef _WIN64
typedef unsigned long long upointer;
inline const char* upointer_format() {static const char s_v[] = "%llu";return s_v;}
inline const char* upointer_format_x() {static const char s_v[] = "0x%llx";return s_v;}
typedef unsigned long long diff_pointer_t;
#else
typedef unsigned long upointer;
inline const char* upointer_format() {static const char s_v[] = "%lu";return s_v;}
inline const char* upointer_format_x() {static const char s_v[] = "0x%lx";return s_v;}
typedef unsigned long diff_pointer_t;
#endif

#elif defined(__MINGW32__)

typedef int int32;
typedef long long int64;
inline const char* int32_format() {static const char s_v[] = "%d";return s_v;}
inline const char* int64_format() {static const char s_v[] = "%ld";return s_v;}

typedef unsigned int uint32;
typedef unsigned long long uint64;
inline const char* uint32_format() {static const char s_v[] = "%u";return s_v;}
inline const char* uint64_format() {static const char s_v[] = "%lu";return s_v;}

#ifdef __MINGW64__
typedef unsigned long long upointer;
inline const char* upointer_format() {static const char s_v[] = "%llu";return s_v;}
inline const char* upointer_format_x() {static const char s_v[] = "0x%llx";return s_v;}
typedef unsigned long long diff_pointer_t;
#else
typedef unsigned long upointer;
inline const char* upointer_format() {static const char s_v[] = "%lu";return s_v;}
inline const char* upointer_format_x() {static const char s_v[] = "0x%lx";return s_v;}
typedef unsigned long diff_pointer_t;
#endif

#elif defined(_LP64)

// 64 Bit Platforms
typedef int int32;
typedef long int64;
inline const char* int32_format() {static const char s_v[] = "%d";return s_v;}
inline const char* int64_format() {static const char s_v[] = "%ld";return s_v;}

typedef unsigned int uint32;
typedef unsigned long uint64;
inline const char* uint32_format() {static const char s_v[] = "%u";return s_v;}
inline const char* uint64_format() {static const char s_v[] = "%lu";return s_v;}

typedef unsigned long diff_pointer_t;

typedef unsigned long upointer;
inline const char* upointer_format() {static const char s_v[] = "%lu";return s_v;}
inline const char* upointer_format_x() {static const char s_v[] = "0x%lx";return s_v;}

#else

// 32-Bit Platforms
typedef int int32;
typedef long long int64;
inline const char* int32_format() {static const char s_v[] = "%d";return s_v;}
inline const char* int64_format() {static const char s_v[] = "%lld";return s_v;}

typedef unsigned int uint32;
typedef unsigned long long uint64;
inline const char* uint32_format() {static const char s_v[] = "%u";return s_v;}
inline const char* uint64_format() {static const char s_v[] = "%llu";return s_v;}

typedef unsigned long diff_pointer_t;

typedef unsigned long upointer;
inline const char* upointer_format() {static const char s_v[] = "%lu";return s_v;}
inline const char* upointer_format_x() {static const char s_v[] = "0x%lx";return s_v;}

#endif

inline uint32 uint32_mx() { //4 294 967 295
  uint32 n = 0;
  for(unsigned int i=0;i<32;i++)  n += 1<<i;
  return n;
}
inline uint64 uint64_mx() { //18 446 744 073 709 551 615
  uint64 one = 1;
  uint64 n = 0;
  for(unsigned int i=0;i<64;i++)  n += one<<i;
  return n;
}

typedef unsigned char byte;

//for ./io :
typedef unsigned char uchar;
typedef short int16;
typedef unsigned short ushort;
typedef unsigned short uint16;
typedef uint32 ref;
typedef char* cstr_t;
typedef const char* const_cstr_t;

class fits_bit {public:char m_c;}; //for exlib/cfitsio
class csv_time {public:long m_l;}; //for rcsv_ntuple

inline unsigned int size_char()   {return 1;}
inline unsigned int size_short()  {return 2;}
inline unsigned int size_int()    {return 4;}
inline unsigned int size_int64()  {return 8;}
inline unsigned int size_float()  {return 4;}
inline unsigned int size_double() {return 8;}

// used in arrout :
inline const char* type_format(float)  {static const char s_v[] = "%g";return s_v;}
inline const char* type_format(double) {static const char s_v[] = "%g";return s_v;}

inline const char* type_format(char)   {static const char s_v[] = "%d";return s_v;}
inline const char* type_format(short)  {static const char s_v[] = "%d";return s_v;}
inline const char* type_format(int)    {static const char s_v[] = "%d";return s_v;}
inline const char* type_format(int64)  {return int64_format();}

inline const char* type_format(unsigned char)  {static const char s_v[] = "%u";return s_v;}
inline const char* type_format(unsigned short) {static const char s_v[] = "%u";return s_v;}
inline const char* type_format(unsigned int)   {static const char s_v[] = "%u";return s_v;}
inline const char* type_format(uint64)         {return uint64_format();}

typedef unsigned int key_code;

}

#endif
