#include "rap.h"
#include "memory.h"
#include "string.h"
#include <ctype.h>
#include <assert.h>
#include "darray.h"
#include "registry.h"

/*--------------------------------------------------*/
char * RapStr_duplicate(s)
char *s;
{
  if (s==NULL)
    return(strcpy(Memory_allocate(1),""));
  else
    return(strcpy(Memory_allocate(strlen(s)+1),
		  s));
}

/*--------------------------------------------------*/
Bool RapStr_is_empty(s)
char *s;
{
  unsigned i,l;
  if (s==NULL) return (Bool_TRUE);
  i=0;
  while (s[i]!='\0') {
    if (!isspace(s[i])) 
      return(Bool_FALSE);
    i++;
  }
  return(Bool_TRUE);
}

/*--------------------------------------------------*/
NORET RapStr_destroy(s)
char *s;
{
  Memory_free(s);
}

/*--------------------------------------------------*/
/* allows leading blanks for a number with inf. digits */
/*----------------------------------------*/
Bool RapStr_is_int(s)
char *s;
{
  int i,l,state;
  assert(s);
  l=strlen(s);
  state=0;

  for (i=0;i<l;i++) {
    if (s[i]==' ') {
      if (state==1) {
	state=2;
      }
    }
    else if (isdigit(s[i])) {
      if (state==2)
	return(Bool_FALSE);
      else
	state=1;
    }
    else
      return(Bool_FALSE);
  }
  if (state==1)
    return(Bool_TRUE);
  else
    return(Bool_FALSE);
}

/*==================================================================*/
/*                                                                  */
/*               RapPack                                            */
/*                                                                  */
/*==================================================================*/

struct RapPack_str {
  int size;
  Darray d;
};

Registry RapPacks=NULL;

/*--------------------------------------------------*/
RapPack RapPack_create2(a,b)
VOIDP a,b;
{
  RapPack p;
  if (RapPacks==NULL)
    RapPacks=Registry_create(Registry_ptrcmp,Registry_ptrhash);
  p=(RapPack)Memory_allocate(sizeof(struct RapPack_str));
  p->size=2;
  p->d=Darray_create();
  Darray_hint(p->d,0,2);
  Darray_addh(p->d,a);
  Darray_addh(p->d,b);
  if (Registry_add(RapPacks,(VOIDP)p,(VOIDP)p)==Bool_FALSE)
    Al_fatal_error("RapPacks: error adding rappack to existance list.");
  return(p);
}

/*--------------------------------------------------*/
RapPack RapPack_create3(a,b,c)
VOIDP a,b,c;
{
  RapPack p;
  if (RapPacks==NULL)
    RapPacks=Registry_create(Registry_ptrcmp,Registry_ptrhash);
  p=(RapPack)Memory_allocate(sizeof(struct RapPack_str));
  p->size=3;
  p->d=Darray_create();
  Darray_hint(p->d,0,3);
  Darray_addh(p->d,a);
  Darray_addh(p->d,b);
  Darray_addh(p->d,c);
  if (Registry_add(RapPacks,(VOIDP)p,(VOIDP)p)==Bool_FALSE)
    Al_fatal_error("RapPacks: error adding rappack to existance list.");
  return(p);
}

/*--------------------------------------------------*/
NORET RapPack_destroy(p)
RapPack p;
{
  if (RapPacks==NULL)
    Al_fatal_error("RapPack:cannot destroy a rappack before any are created.");
  if (Registry_remove(RapPacks,(CONSTVOIDP)p)==Bool_FALSE)
    Al_fatal_error("RapPack:cannot destroy a rappack which does not exist.");
  Darray_destroy(p->d);
  Memory_free(p);
}

/*..................................................*/    
NORET RapPack_kill_one(k,v,d)
VOIDP k,v,d;
{
  RapPack p;
  p=(RapPack)k;
  if (Registry_remove(RapPacks,(CONSTVOIDP)p)==Bool_FALSE)
    Al_fatal_error("RapPack:cannot destroy a rappack which does not exist.");
  Darray_destroy(p->d);
  Memory_free(p);
  Registry_remove(RapPacks,p);
}
/*--------------------------------------------------*/
NORET RapPack_destroy_all()
{
  if (RapPacks==NULL)
    Al_fatal_error("RapPack:cannot destroy all rappacks before any are\
 created.");
  Registry_traverse(RapPacks,RapPack_kill_one,(VOIDP)NULL);
  Registry_destroy(RapPacks);
  RapPacks=NULL;
}

/*--------------------------------------------------*/
VOIDP RapPack_get(p,n)
RapPack p;
int n;
{
#ifdef RE_DEBUG
  if (RapPacks==NULL)
    Al_fatal_error("RapPack_get:can't before any are created.");
  if (Registry_get(RapPacks,p)==NULL)
    Al_fatal_error("RapPack_get: passed in invalid rappack.");
#else
  assert(RapPacks);
  assert(p);
#endif

  if (n<0)
    Al_fatal_error("RapPack:can not get negative compnent of a rappack");
  if (n>=p->size)
    Al_fatal_error("RapPack:can not get compnent of a rappack: index too\
  large");

  return(Darray_get(p->d,n));
}
