
/******************************************************************************
* MODULE     : array.gen.cc
* DESCRIPTION: fixed size arrays with reference counting
* COPYRIGHT  : (C) 1999  Joris van der Hoeven
*******************************************************************************
* This software falls under the GNU general public license and comes WITHOUT
* ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
* If you don't have this file, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
******************************************************************************/

#include <array.gen.h>

#module code_array (T)
#import array (T)

/******************************************************************************
* Routines intern to the array<T> class
******************************************************************************/

static inline int
round_length<T> (int n) {
  if (n<6) return n;
  register int i=8;
  while (n>i) i<<=1;
  return i;
}

array_rep<T>::array_rep<T>(int n2):
  n(n2), a((n==0)?((T*) NULL):(new T[round_length<T>(n)])) {}

void
array_rep<T>::resize (register int m) {
  register int nn= round_length<T> (n);
  register int mm= round_length<T> (m);
  if (mm != nn) {
    if (mm != 0) {
      register int i, k= (m<n? m: n);
      T* b= new T[mm];
      for (i=0; i<k; i++) b[i]= a[i];
      if (nn != 0) delete[] a;
      a= b;
    }
    else {
      if (nn != 0) delete[] a;
      a= NULL;
    }
  }
  n= m;
}

array<T>::array<T> (T* a, int n) {
  register int i;
  rep= new array_rep<T>(n);
  for (i=0; i<n; i++)
    rep->a[i]=a[i];
}

array<T>::operator tree () {
  int i, n=rep->n;
  tree t (TUPLE, n);
  for (i=0; i<n; i++)
#ifdef no_tree_converter<T>
    t[i]= "?";
#else
    t[i]= (tree) rep->a[i];
#endif
  return t;
}

/******************************************************************************
* Other routines on arrays
******************************************************************************/

bool
operator == (array<T> a, array<T> b) {
  register int i;
  if (N(a)!=N(b)) return FALSE;
  for (i=0; i<N(a); i++)
    if (a[i]!=b[i]) return FALSE;
  return TRUE;
}

bool
operator != (array<T> a, array<T> b) {
  register int i;
  if (N(a)!=N(b)) return TRUE;
  for (i=0; i<N(a); i++)
    if (a[i]!=b[i]) return TRUE;
  return FALSE;
}

ostream&
operator << (ostream& out, array<T> a) {
  int i;
  
  if (N(a)==0) return out << "[ ]";
  out << "[ ";
  for (i=0; i<N(a)-1; i++)
    out << a[i] << ", ";
  if (N(a)!=0) out << a[i];
  out << " ]";
  return out;
}

array<T>&
operator << (array<T>& a, T x) {
  a->resize (N(a)+ 1);
  a[N(a)-1]=x;
  return a;
}

array<T>&
operator << (array<T>& a, array<T> b) {
  register int i, k= N(a);
  a->resize (N(a)+ N(b));
  for (i=0; i<N(b); i++) a[i+k]= b[i];
  return a;
}

#endmodule // code_array (T)
