// Change History:
// 12/03/03 AV Development: Add AT_Num64 type for 64 bit values
// 10/27/03 AV Production: Add AT_Num typedef for all numeric data

// Basic ATSI data types

#ifndef ATSI_TYPES_H
#define ATSI_TYPES_H

#include <assert.h>
#include <stdlib.h>

#include <vector>

using namespace std;

typedef unsigned char byte;

class AT_String
{
public :
  AT_String
    (const byte *s = 0) :
      str(s)
  {};

  AT_String
    (const char *s) :
      str((byte*)s)
  {};

  AT_String
    (int) :
    str(0)
  {};

  AT_String& operator=
    (char *const rhs)
  { str = (const byte*) rhs; return *this; };

  AT_String& operator=
    (byte *const rhs)
  { str = rhs; return *this; };

  bool operator!
    ()
    const
  { return !str; };

  operator const byte *
    ()
    const
  { return str; };

  operator const char *
    ()
    const
  { return (const char*) str; };

  byte operator*
    ()
    const
  { return *str; };

private :
  const byte* str;
};

typedef unsigned int   uint;
typedef unsigned long  ulong;

typedef unsigned int uint32;
typedef int int32;
typedef unsigned short uint16;
typedef short int16;
typedef unsigned char uint8;

#define MAXUINT   ((uint)-1)
#define MAXUINT8  ((uint8) -1)
#define MAXUINT16 ((uint16)-1)
#define MAXUINT32 ((uint32)-1)
#define MAXUINT64 ((uint64)(-1))

typedef unsigned char bool8;

// 24-bit unsigned integer
class uint24
{
public :
  uint24
    (uint32 n = 0);

  operator uint32
    ()
    const;

private :
  byte  val[3];
};

typedef unsigned __int64 uint64;
typedef __int64 int64;

// 64 bit conversion will use AT_Num type for all vector types and index terms

typedef int64 AT_Num;
typedef uint64 AT_UNum;
#define AT_MAXNUM 0x7FFFFFFFFFFFFFFF
#define atoAT_Num(a) _atoi64((const char *)a)
#define AT_Numtoa(num, a) _i64toa(num, (char *)a, 10)

/*
AV 3/2/05 - flip engine to use 64 bit numbers !

// Currently use 32 bit values
typedef uint32 AT_Num;
typedef uint32 AT_UNum;
#define AT_MAXNUM MAXUINT32
#define atoAT_Num(a) (AT_Num)std::atol(a)
#define AT_Numtoa(num, a) std::ultoa(num, a, 10)
*/

// 64 bit num
typedef int64 AT_Num64;
#define AT_MAXNUM64 0x7FFFFFFFFFFFFFFF
#define atoAT_Num64(a) _atoi64(a)
#define AT_Num64toa(num, a) _i64toa(num, a, 10)

inline uint64 _make64
  (uint32 lo,
   uint32 hi)
{
  return (((uint64) hi) << 32) | lo;
}

inline uint32 _get32
  (uint64 u64,
   uint32* hi)
{
  *hi = (uint32)(u64 >> 32);
  return (uint32) u64;
}

// paths and files
//#include <windows>
#ifdef WIN16
enum { MAX_PATH = 128 };
#else
#if !defined MAX_PATH
#define MAX_PATH 260
#endif
#endif

class fullFileName
{
public:
  fullFileName
    ()
  { file_name[0] = 0; };
    
  fullFileName
    (AT_String fn)
  { strcpy_s((char*)file_name, sizeof(file_name), (const char*)fn); }

  fullFileName
    (fullFileName& rhs)
  { strcpy_s((char*)file_name, sizeof(file_name), (char*)rhs.file_name); }

  fullFileName& operator=
    (AT_String rhs)
  { strcpy_s((char*)file_name, sizeof(file_name), rhs); return *this; };

  fullFileName& operator=
    (char *const rhs)
  { strcpy_s((char*)file_name, sizeof(file_name), rhs); return *this; };

  fullFileName& operator=
    (byte *const rhs)
  { strcpy_s((char*)file_name, sizeof(file_name), (char*)rhs); return *this; };

  bool operator!
    ()
    const
  { return (file_name[0] == 0); };

  byte operator*
    ()
    const
  { return *file_name; };

  operator byte*
    ()
  { return file_name; }

  operator const byte*
    ()
    const
  { return file_name; }

  operator char*
    ()
  { return (char*) file_name; }

  operator const char*
    ()
    const
  { return (const char*) file_name; }

  operator AT_String
    ()
  { return AT_String(file_name); }

  operator AT_String
    ()
    const
  { return AT_String(file_name); }

  byte& operator[]
    (uint i)
  { return file_name[i]; }

  const char* c_name
    ()
    const
  { return (const char*) file_name; }
  
private:
  byte file_name[MAX_PATH + 1];
};

#define loop while(1)

#ifdef NDEBUG
#define CHECKHEAP
#else
//#include <alloc>
#define CHECKHEAP (assert(heapcheck() > 0))
#endif

class reportProgress
{
public :
  virtual ~reportProgress
    ()
  {};

  // return false to cancel
  virtual bool progress
    (uint32 current,
     uint32 total)
   = 0;
};

template <class T>
class auto_array
{
public:
  explicit auto_array
    (T* p = 0);

  auto_array
    (auto_array<T>& rhs);

  auto_array<T>& operator=
    (auto_array<T>& rhs);

  auto_array<T>& operator=
    (T* rhs)
  { reset(rhs); return *this; };

  ~auto_array
    ();

  bool operator!
    ()
    const;

  T& operator*
    ()
    const;
  T* operator->
    ()
    const;
  T& operator[]
    (uint i)
    const;

  T* get
    ()
    const;
  T* release
    ();
  void reset
    (T* p = 0);

private :
  T* ptr;
};

// ================================== INLINE AUTO_ARRAY =======

template <class T> inline
auto_array<T>::auto_array
  (T* p) :
    ptr(p)
{
}

template <class T> inline
auto_array<T>::auto_array
  (auto_array<T>& rhs) :
    ptr(rhs.release())
{
}

template <class T> inline
auto_array<T>& auto_array<T>::operator=
  (auto_array<T>& rhs)
{
  if (this != &rhs)
    reset(rhs.release());
  return *this;
}

template <class T> inline
auto_array<T>::~auto_array
  ()
{
  delete [] ptr;									
}

template <class T> inline
bool auto_array<T>::operator!
  ()
  const
{
  return !ptr;
}

template <class T> inline
T& auto_array<T>::operator*
  ()
  const
{
  return *ptr;
}

template <class T> inline
T& auto_array<T>::operator[]
  (uint i)
  const
{
  return *(ptr + i);
}

template <class T> inline
T* auto_array<T>::operator->
  ()
  const
{
  return ptr;
}

template <class T> inline
T* auto_array<T>::get
  ()
  const
{
  return ptr;
}

template <class T> inline
T* auto_array<T>::release
  ()
{
  T* old = ptr;
  ptr = 0;
  return old;
}

template <class T> inline
void auto_array<T>::reset
  (T* p)
{
  delete [] ptr;
  ptr = p;
}

template <class T>
class vector_ptr
{
public:
  vector_ptr
    ()
  {}
  
  vector_ptr
    (T* start,
     T* end) :
    v(start, end)
  {}

  vector_ptr
    (const std::vector<T>& vec) :
    v(vec)
  {}
  
  ~vector_ptr
    ()
  {clearAll();}

  void clear
    ()
  {
    clearAll();
    v.clear();
  }
  
  vector_ptr<T>& operator =
    (std::vector<T>& rhs)
  {
    clearAll();
    
    v = rhs;
    return *this;
  }
  vector_ptr<T>& operator =
    (vector_ptr<T>& rhs)
  {
    clearAll();

    v = rhs.v;
    rhs.releaseAll();
    
    return *this;
  }

  const std::vector<T>& get
    ()
    const
  { return v; }

  T operator []
    (uint n)
    const
  { return v[n]; }

  void push_back
    (T item)
  { v.push_back(item); }

  void setAt
    (uint pos,
     T item);

  bool removeAt
    (uint pos);

  void resize
    (uint newSize);

  uint size
    ()
    const
  { return v.size(); }

  uint findPos
    (T p);
    
private:
  void clearAll
    ();

  void releaseAll
    ();
    
  std::vector<T> v;
};

template <class T>
inline void vector_ptr<T>::setAt
  (uint pos,
   T item)
{
  if (pos >= v.size())
    v.resize(pos + 1, NULL);

  delete v[pos];
  v[pos] = item;
}

template <class T>
bool vector_ptr<T>::removeAt
  (uint pos)
{
  setAt(pos, NULL);
  for (uint i = pos + 1; i < v.size(); ++i)
    v[i - 1] = v[i];

  v.resize(v.size() - 1);
}

template <class T>
void vector_ptr<T>::resize
  (uint newSize)
{
  if (newSize > v.size())
    v.resize(newSize, NULL);
  else if (newSize < v.size())
  {
    for (uint i = newSize; i < v.size(); ++i)
      setAt(i, NULL);

    v.resize(newSize);
  }
}

template <class T>
uint vector_ptr<T>::findPos
  (T p)
{
  uint pos = 0;
  for (v::iterator it = v.begin(); it != v.end(); it++, ++pos)
    if (*it == p)
      return pos;

  return MAXUINT;
}

template <class T>
void vector_ptr<T>::clearAll
  ()
{
  for (std::vector<T>::iterator it = v.begin(); it != v.end(); it++)
  {
    delete *it;
    *it = NULL;
  }
}

template <class T>
void vector_ptr<T>::releaseAll
  ()
{
  for (std::vector<T>::iterator it = v.begin(); it != v.end(); it++)
    *it = NULL;
}

#ifdef  USE_AT_ERROR_H
# include "at_error.h"
#endif

#endif
 