/*
 * Copyright (c) 2004, Stony Brook University
 * Contributors: Ashish Raniwala
 * All rights reserved.
 *
 * See copyright notice included in the distribution for details
 *
 */

// raniwala: added for manual routing in wireless scenario
//
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "fixedrtable.h"

static int rtent_trich(const void *a, const void *b) {

  nsaddr_t ia = ((const fixed_rtable_ent *) a)->dst;
  nsaddr_t ib = ((const fixed_rtable_ent *) b)->dst;

  int ta = ((const fixed_rtable_ent *) a)->tag;
  int tb = ((const fixed_rtable_ent *) b)->tag;

  if (ia > ib) return 1;
  if (ib > ia) return -1;
  if (ta > tb) return 1;
  if (tb > ta) return -1;

  return 0;
}

FixedRoutingTable::FixedRoutingTable() {
  // Let's start with a ten element maxelts.
  elts = 0;
  maxelts = 10;
  rtab = new fixed_rtable_ent[maxelts];
}

void
FixedRoutingTable::AddEntry(const fixed_rtable_ent &ent)
{
  fixed_rtable_ent *it;

  printf("RouteTable: Adding destination %d tag %d\n", ent.dst, ent.tag);

  if ((it = (fixed_rtable_ent*) bsearch(&ent, rtab, elts, sizeof(fixed_rtable_ent), 
				 rtent_trich))) {
    bcopy(&ent,it,sizeof(fixed_rtable_ent));
    return;
  }

  if (elts == maxelts) {
    fixed_rtable_ent *tmp = rtab;
    maxelts *= 2;
    rtab = new fixed_rtable_ent[maxelts];
    bcopy(tmp, rtab, elts*sizeof(fixed_rtable_ent));
    delete tmp;
  }
  
  int max;
  
  for (max=0;max<elts;max++) {
	  if ((ent.dst < rtab[max].dst)  ||
	      ((ent.dst == rtab[max].dst) && (ent.tag < rtab[max].tag)) )
	  {
		  break;
	  }
  }
  // Copy all the further out guys out yet another.
  int i = elts-1;
  while (i >= max) 
	  rtab[i+1] = rtab[i--];
  bcopy(&ent, &rtab[max], sizeof(fixed_rtable_ent));
  elts++;

  return;
}

void 
FixedRoutingTable::InitLoop() {
  ctr = 0;
}

fixed_rtable_ent *
FixedRoutingTable::NextLoop() {
  if (ctr >= elts)
    return 0;

  return &rtab[ctr++];
}

// Only valid (duh) as long as no new routes are added
int 
FixedRoutingTable::RemainingLoop() {
  return elts-ctr;
}

fixed_rtable_ent *
FixedRoutingTable::GetEntry(nsaddr_t dest, int tag) {
  fixed_rtable_ent ent;
  ent.dst = dest;
  ent.tag = tag;
  printf("RouteTable: Searching for destination %d tag %d\n", dest, tag);
  return (fixed_rtable_ent *) bsearch(&ent, rtab, elts, sizeof(fixed_rtable_ent), 
				rtent_trich);
}
