/*
   File:        iqueue.h
   Author:      Dan Pelleg
   Created:     Tue Aug 21 18:40:07 EDT 2001
   Description: a simple bounded, cyclic, integer queue

   $Id: iqueue.c,v 1.2 2003/12/24 18:52:56 pgunn Exp $

   Copyright 2001, Dan Pelleg
*/

#include "iqueue.h"
#include "amma.h"

iqueue* mk_empty_iqueue(int maxelems)
{
  iqueue *ret = (iqueue *) am_malloc(sizeof(iqueue));
  ret->q = mk_ivec(maxelems);
  ret->next_pos = 0;
  ret->nelems = 0;
  ret->size = maxelems;
  return ret;
}

void free_iqueue(iqueue *iq)
{
  free_ivec(iq->q);
  am_free((void *)iq, sizeof(iqueue));
}

bool iqueue_is_empty(const iqueue *iq)
{
  return iq->nelems == 0;
}

bool ienqueue(iqueue *iq, int key)
{
  /* is this operation going to fill the queue? */
  if(iq->nelems == iq->size)
    return FALSE;

  /* all is fine; enqueue */
  ivec_set(iq->q, iq->next_pos, key);
  iq->next_pos = (iq->next_pos + 1) % iq->size;
  iq->nelems++;

  return TRUE;
}

int idequeue(iqueue *iq)
{
  int ret;

  if(iq->nelems == 0)
    my_error("iqueue: idequeue called on an empty queue");

  /* note we're adding iq->size just to make sure the result of the
     mod operation is nonnegative */
  ret = ivec_ref(iq->q, (iq->size + iq->next_pos - iq->nelems) % iq->size);

  iq->nelems--;

  return ret;
}

void fprintf_iqueue(FILE* fp, const char* m1, const iqueue *iq, const char* m2)
{
  int i;

  if(iq->nelems == 0) {
    fprintf(fp, "%s is an empty queue%s", m1, m2);
    return;
  }

  fprintf(fp, "%s = {%s", m1, m2);

  for(i=iq->next_pos - iq->nelems; i < iq->next_pos; i++) {
    fprintf(fp, "%d%s", ivec_ref(iq->q, (iq->size + i) % iq->size), m2);
  }
  fprintf(fp, "}%s", m2);

}

#if 0
void test_iqueue()
{
  iqueue *q = mk_empty_iqueue(5);
  puts("empty queue");
  fprintf_iqueue(stdout, "q", q, "\n");

  ienqueue(q, 3);
  puts("3 put in");
  fprintf_iqueue(stdout, "q", q, "\n");

  if(!(ienqueue(q, 7) && ienqueue(q, 6) &&  ienqueue(q, 2)))
    my_error("oops, could not enqueue");
  puts("7,6,2 put in");
  fprintf_iqueue(stdout, "q", q, "\n");

  if(idequeue(q) != 3)
    my_error("oops, did not dequeue 3");
  puts("3 taken out");
  fprintf_iqueue(stdout, "q", q, "\n");

  if(!(ienqueue(q, 25) && ienqueue(q, 76)))
    my_error("oops, could not enqueue");

  puts("25, 76, put in");
  fprintf_iqueue(stdout, "q", q, "\n");

  if(idequeue(q) != 7)
    my_error("oops, did not dequeue 7");
  if(idequeue(q) != 6)
    my_error("oops, did not dequeue 6");
  if(idequeue(q) != 2)
    my_error("oops, did not dequeue 2");
  if(idequeue(q) != 25)
    my_error("oops, did not dequeue 2");
  if(idequeue(q) != 76)
    my_error("oops, did not dequeue 2");
  puts("all taken out");
  fprintf_iqueue(stdout, "q", q, "\n");

  if(!(ienqueue(q, 17) && ienqueue(q, 16) &&  ienqueue(q, 12)))
    my_error("oops, could not enqueue");
  puts("17,16,12 put in");
  fprintf_iqueue(stdout, "q", q, "\n");
  if(idequeue(q) != 17)
    my_error("oops, did not dequeue 17");
  if(idequeue(q) != 16)
    my_error("oops, did not dequeue 16");
  if(idequeue(q) != 12)
    my_error("oops, did not dequeue 12");

}

#endif /* 0 */
