
/*
   File:        amcv.c
*/

#include "amcv.h"

/* Private headers */
static void check_cvec_code(cvec *cv,char *name);
static void fprintf_chars(FILE* s, char* message1, char* chars, int size, char* message2);
static void fprintf_cvec(FILE* s, char* m1, const cvec* cv, char* m2);
static void check_cvec_access(cvec *cv,int i, char *name);

/* Unused private function headers */
#ifdef AUTON_UNUSED_CODE
static void assert_cvec_shape(cvec *cv,int size,char *name);
#endif /* AUTON_UNUSED_CODE */

#define CVEC_CODE 28541

int Cvecs_mallocked = 0;
int Cvecs_freed = 0;

static void check_cvec_code(cvec *cv,char *name)
{
  if ( cv == NULL )
  {
    fprintf(stderr,"NULL cvec passed in operation %s\n",name);
    my_error("cvec data structure");
  }
  if ( cv->cvec_code != CVEC_CODE )
  {
    fprintf(stderr,"Attempt to access a non-allocated Integer Vector\n");
    fprintf(stderr,"This is in the operation %s\n",name);
    my_error("cvec data structure error");
  }
  if ( cv->array_size < cv->size )
    my_error("check_cvec_code: array_size and size muddled");
}

static void fprintf_chars(FILE* s, char* message1, char* chars, int size,
		   char* message2)
{
  int i;
  fprintf(s, "%s ", message1);

  if (chars == NULL && size > 0)
    fprintf(s, "(char *)NULL");
  else
    {
      fprintf(s, "{ ");
      for (i = 0; i < size; i++)
	fprintf(s,"%d %s", (int)chars[i], (i == size-1) ? "" : ", ");
      fprintf(s, "}");
    }
  fprintf(s, " %s", message2);
}

static void fprintf_cvec(FILE* s, char* m1, const cvec* cv, char* m2)
{
  if (cv == NULL)
    fprintf(s, "%s = (cvec*)NULL%s", m1, m2);
  else
    {
      char buf[100];
      check_cvec_code((cvec*)cv, "fprintf_cvec");
      sprintf(buf, "%s = ", m1);
      fprintf_chars(s, buf, cv->carr, cv->size, m2);
    }
}

static void check_cvec_access(cvec *cv,int i, char *name)
{
  check_cvec_code(cv,name);

  if ( i < 0 || i >= cv->size )
  {
    fprintf(stderr,"In operation \"%s\"\n",name);
    fprintf(stderr,"the cvec (int integer vector) has size = %d\n",cv->size);
    fprintf(stderr,"You tried to use index i=%d\n",i);
    fprintf(stderr,"Here is the cvec that was involved:\n");
    fprintf_cvec(stderr,"cvv",cv,"\n");
    my_error("check_cvec_access");
  }
  if ( cv->array_size < cv->size )
    my_error("check_cvec_code: array_size and size muddled");
}

/* Nobody was using this... */
#ifdef AUTON_UNUSED_CODE
static void assert_cvec_shape(cvec *cv,int size,char *name)
{
  check_cvec_code(cv,name);

  if ( size != cv->size )
  {
    fprintf(stderr,"In operation \"%s\"\n",name);
    fprintf(stderr,"the cvec (int dynamic vector) has size = %d\n", cv->size);
    fprintf(stderr,"But should have been predefined with the shape:\n");
    fprintf(stderr,"size = %d\n",size);
    my_error("assert_cvec_shape");
  }
}
#endif /* AUTON_UNUSED_CODE */

cvec *mk_cvec(int size)
{
  cvec *result = AM_MALLOC(cvec);
  if ( size < 0 ) my_error("mk_cvec : size < 0 illegal");
  result -> cvec_code = CVEC_CODE;
  result -> array_size = size;
  result -> size = size;
  result -> carr = AM_MALLOC_ARRAY(char, size);
  Cvecs_mallocked += 1;
  return(result);
}

void free_cvec(cvec *cv)
{
  check_cvec_code(cv,"free_cvec");
  cv -> cvec_code = 7777;

  AM_FREE_ARRAY(cv->carr, char, cv->array_size);
  am_free((char *)cv,sizeof(cvec));

  Cvecs_freed += 1;
}


char safe_cvec_ref(cvec *cv, int i)
{
  check_cvec_access(cv,i,"cvec_ref");
  return(cv->carr[i]);
}

void safe_cvec_set(cvec *cv,int i,char value)
{
  check_cvec_access(cv,i,"cvec_set");
  cv->carr[i] = value;
}

void cvec_increment(cvec *cv,int i,char value)
{
  check_cvec_access(cv,i,"cvec_increment");
  cv->carr[i] += value;
}

int cvec_size(cvec *cv)
{
  check_cvec_code(cv,"cvec_size");
  return(cv->size);
}

void constant_cvec(cvec *cv,char value)
{
  int i;
  for ( i = 0 ; i < cvec_size(cv) ; i++ )
    cvec_set(cv,i,value);
}

cvec *mk_constant_cvec(int size,char value)
{
  cvec *cv = mk_cvec(size);
  constant_cvec(cv,value);
  return(cv);
}

void copy_cvec(cvec *cv,cvec *r_cv)
{
  int i;
  for (i = 0; i < cvec_size(cv); i++)
    {
      cvec_set(r_cv, i, cvec_ref(cv, i));
    }

}

cvec *mk_copy_cvec(cvec *cv)
{
  cvec *result = mk_cvec(cvec_size(cv));
  copy_cvec(cv,result);
  return(result);
}

