/*
File: saarray.cpp
Author: Andrew Moore


*/

#include "saarray.h"
#include "amma.h"

#define INITIAL_sa_array_SIZE 10

sa_array *mk_empty_sa_array(void)
{
  sa_array *sa_arr = AM_MALLOC(sa_array);
  sa_arr -> size = 0;
  sa_arr -> array_size = INITIAL_sa_array_SIZE;
  sa_arr -> array = AM_MALLOC_ARRAY(string_array_ptr,sa_arr->array_size);
  return(sa_arr);
}

/* Creates sized sa_array with all elements NULL. */
sa_array *mk_sa_array( int size)
{
  int i;
  sa_array *saa;

  saa = AM_MALLOC( sa_array);
  saa->size = size;
  saa->array_size = int_max( INITIAL_sa_array_SIZE, size);
  saa->array = AM_MALLOC_ARRAY( string_array_ptr, saa->array_size);
  for (i=0; i < saa->array_size; ++i) saa->array[i] = NULL;

  return saa;
}

void add_to_sa_array(sa_array *sa_arr,string_array *sa)
/*
     Assume sa_arr is previously of size n. After this it is of size
   n+1, and the n+1'th element is a COPY of sa.
*/
{
  if ( sa_arr -> size == sa_arr -> array_size )
  {
    int new_size = 2 + 2 * sa_arr->array_size;
    string_array **new_array = AM_MALLOC_ARRAY(string_array_ptr,new_size);
    int i;
    for ( i = 0 ; i < sa_arr -> array_size ; i++ )
      new_array[i] = sa_arr->array[i];
    AM_FREE_ARRAY(sa_arr->array,string_array_ptr,sa_arr->array_size);
    sa_arr -> array = new_array;
    sa_arr -> array_size = new_size;
  }
  sa_arr->array[sa_arr->size] = (sa==NULL) ? NULL : mk_copy_string_array(sa);
  sa_arr->size += 1;
}

int sa_array_size(sa_array *sa_arr)
{
  return(sa_arr->size);
}

string_array *sa_array_ref(sa_array *sa_arr,int index)
/*
     Returns a pointer (not a copy) to the index'th element stored in
   the sa_arr. Error if index < 0 or index >= size
*/
{
  string_array *result;
  if ( index < 0 || index >= sa_array_size(sa_arr) )
  {
    result = NULL;
    my_error("sa_array_ref");
  }
  else
    result = sa_arr->array[index];
  return(result);
}

/* Copies string_array sa. */
void sa_array_set( sa_array *saa, int index, string_array *sa)
{
  string_array *old;

  if (index<0 || index >= sa_array_size( saa)) {
    my_errorf( "sa_array_set: index %d out of bounds [%d,%d].",
	       index, 0, sa_array_size(saa)-1);
  }

  old = sa_array_ref( saa, index);
  if (old != NULL) free_string_array( old);
  saa->array[index] = (sa==NULL) ? NULL : mk_copy_string_array( sa);

  return;
}
  
void fprintf_sa_array(FILE *s,char *m1,sa_array *sa_arr,char *m2)
{
  if ( sa_array_size(sa_arr) == 0 )
    fprintf(s,"%s = <sa_arr with zero ensaies>%s",m1,m2);
  else
  {
    int i;
    for ( i = 0 ; i < sa_array_size(sa_arr) ; i++ )
    {
      string_array *sa = sa_array_ref(sa_arr,i);
      char buff[100];
      sprintf(buff,"%s[%2d]",m1,i);

      if ( sa == NULL )
	fprintf(s,"%s = NULL%s",buff,m2);
      else
	fprintf_string_array(s,buff,sa,m2);
    }
  }
}

void psa_array(sa_array *saarr)
{
  fprintf_sa_array(stdout,"saarr",saarr,"\n");
}

void free_sa_array(sa_array *sa_arr)
{
  int i;
  for ( i = 0 ; i < sa_array_size(sa_arr) ; i++ )
  {
    string_array *sa = sa_arr->array[i];
    if ( sa != NULL ) free_string_array(sa);
  }
  AM_FREE_ARRAY(sa_arr->array,string_array_ptr,sa_arr->array_size);
  AM_FREE(sa_arr,sa_array);
}

sa_array *mk_copy_sa_array(sa_array *sa_arr)
{
  sa_array *new_ar = mk_empty_sa_array();
  int i;

  for ( i = 0 ; i < sa_array_size(sa_arr) ; i++ )
    add_to_sa_array(new_ar,sa_array_ref(sa_arr,i));

  return(new_ar);
}

/* Returns an sa_array of length size in which each element is
   an string_array of length zero. */
sa_array *mk_array_of_zero_length_string_arrays(int size)
{
  sa_array *saa = mk_empty_sa_array();
  string_array *empty = mk_string_array(0);
  int i;

  for ( i = 0 ; i < size ; i++ )
    add_to_sa_array(saa,empty);

  free_string_array(empty);

  return saa;
}
