lpc4/lib/
lpc4/lib/doc/efun/
lpc4/lib/doc/lfun/
lpc4/lib/doc/operators/
lpc4/lib/doc/simul_efuns/
lpc4/lib/doc/types/
lpc4/lib/etc/
lpc4/lib/include/
lpc4/lib/include/arpa/
lpc4/lib/obj/d/
lpc4/lib/save/
lpc4/lib/secure/
lpc4/lib/std/
lpc4/lib/std/living/
#include "global.h"
#include "array.h"
#include "interpret.h"
#include "list.h"
#include "object.h"
#include "stralloc.h"
#include "mapping.h"

void free_list(struct vector *v) { free_vector(v); }

struct vector *allocate_list(struct vector *v)
{
    struct vector *m;

    m = allocate_array_no_init(1,0);
    m->item[0].u.vec = v;
    m->item[0].type = T_ALIST_PART;
    return m;
}

struct vector *mklist(struct vector *v)
{
  v=allocate_list(slice_array(v,0,v->size));
  order_alist(v);
  return v;
}

void mutilate_mapping(struct vector *a,int ap,struct vector *b,int bp)
{
  assign_svalue_raw(&(a->item[0].u.vec->item[ap]),&(b->item[0].u.vec->item[bp]));
  assign_svalue_raw(&(a->item[1].u.vec->item[ap]),&(b->item[1].u.vec->item[bp]));
}

void list_assign(struct vector *a,int ap,struct vector *b,int bp)
{
  assign_svalue_raw(&(a->item[0].u.vec->item[ap]),&(b->item[0].u.vec->item[bp]));
}

void array_assign(struct vector *a,int ap,struct vector *b,int bp)
{
  assign_svalue_raw(&(a->item[ap]),&(b->item[0].u.vec->item[bp]));
}


/*
 * This function handles or, xor, and, sub on lists, mapping and arrays
 * /Profezzorn
 */

struct vector *do_array_surgery(
		struct vector *a,
		struct vector *b,
		int op,
		int type )
{
  register int ap,bp,d,num;
  int asize,bsize;
  struct vector *ret;
  struct svalue *ap2,*bp2;
  struct svalue *ap3,*bp3;
  void (*assignfunc)(struct vector *,int,struct vector *,int);

  asize=bsize=0; ap2=bp2=0; assignfunc=0; /* make gcc happy */
  switch(type)
  {
    case T_POINTER:	/* All surgery on arrays return alists */
      {
        struct vector *tt;
        tt=allocate_array_no_init(1,0);
        tt->item[0].type=T_POINTER;
        tt->item[0].u.vec=slice_array(a,0,a->size-1);
        order_alist(a=tt);

        tt=allocate_array_no_init(1,0);
        tt->item[0].type=T_POINTER;
        tt->item[0].u.vec=slice_array(b,0,b->size-1);
        order_alist(b=tt);

	asize=a->item[0].u.vec->size;
	bsize=b->item[0].u.vec->size;
	ap2=& a->item[0].u.vec->item[0];
	bp2=& b->item[0].u.vec->item[0];
	assignfunc=&array_assign;
      }
      break;

    case T_LIST:
      asize=a->item[0].u.vec->size;
      bsize=b->item[0].u.vec->size;
      ap2=& a->item[0].u.vec->item[0];
      bp2=& b->item[0].u.vec->item[0];
      assignfunc=&list_assign;
      break;
    case T_MAPPING:
      asize=a->item[0].u.vec->size;
      bsize=b->item[0].u.vec->size;
      ap2=& a->item[0].u.vec->item[0];
      bp2=& b->item[0].u.vec->item[0];
      assignfunc=&mutilate_mapping;
      break;
  }
  num=ap=bp=0;
  ap3=ap2;
  bp3=bp2;

  while(ap<asize && bp<bsize)
  {
    d=alist_cmp(ap2,bp2);

    if(!d) d=op & 7;
    else if(d<0) d=op>>4 & 7;
    else d=op>>8 & 7;

    switch(d)
    {
      case GETA:
        num++;
      case NOTA:
        ap++;
        ap2++;
        break;

      case GETB:
        num++;
      case NOTB:
        bp++;
        bp2++;
        break;

      case BOTH:
	num++;
      case EITHER:
	num++;
      case NONE:
        ap++;
        ap2++;
        bp++;
        bp2++;
       
    }
  }
  if(OPER_A_TAKE==(op & 0x0f0) ) num += asize-ap;
  if(OPER_B_TAKE==(op & 0xf00) ) num += bsize-bp;

  if(type==T_MAPPING)
    ret=allocate_mapping(allocate_array_no_init(num,0),allocate_array_no_init(num,0));
  else if(type==T_LIST)
    ret=allocate_list(allocate_array_no_init(num,0));
  else
    ret=allocate_array_no_init(num,0);

  num=ap=bp=0;
  ap2=ap3;
  bp2=bp3;

  while(ap<asize && bp<bsize)
  {
    d=alist_cmp(ap2,bp2);

    if(!d) d=op & 7;
    else if(d<0) d=op>>4 & 7;
    else d=op>>8 & 7;

    switch(d)
    {
      case GETA:
        assignfunc(ret,num++,a,ap);
      case NOTA:
        ap++;
        ap2++;
        break;
      case GETB:
        assignfunc(ret,num++,b,bp);
      case NOTB:
        bp++;
        bp2++;
        break;

      case BOTH:
        assignfunc(ret,num++,a,ap);
      case EITHER:
        assignfunc(ret,num++,b,bp);
      case NONE:
        bp++;
        ap++;
        bp2++;
        ap2++;
    }
  }

  if(OPER_A_TAKE==(op & 0x0f0)) while(ap<asize) assignfunc(ret,num++,a,ap++);
  if(OPER_B_TAKE==(op & 0xf00)) while(bp<bsize) assignfunc(ret,num++,b,bp++);

  if(type==T_POINTER)
  {
    free_vector(a);
    free_vector(b);
  }
  return ret;  
}

/* Ha ha Now I can clean the shit out in a quick manner ! */
struct vector *cleanup_map(struct vector *map)
{
  int size,e,newsize;
  struct svalue *i,*v,*ii,*vv,*def;
  struct vector *indices,*values,*ret;

  check_alist_for_destruct(map);

  size=map->item[0].u.vec->size;
  def=& map->item[2];

  newsize=0;
  v=& map->item[1].u.vec->item[0];
  for(e=0;e<size;e++,v++)
    if(alist_cmp(def,v))
      newsize++;

  indices=allocate_array_no_init(newsize,0);
  values=allocate_array_no_init(newsize,0);

  i=& map->item[0].u.vec->item[0];
  v=& map->item[1].u.vec->item[0];
  ii=& indices->item[0];
  vv=& values ->item[0];
  for(e=0;e<size;e++)
  {
    if(alist_cmp(def,v))
    {
      assign_svalue_raw(ii++,i);
      assign_svalue_raw(vv++,v);
    }
    i++; v++;
  }
  ret=allocate_mapping(indices,values);
  assign_svalue(map->item+2,ret->item+2);
  return ret;
}