/*******************************************************************
 *                  Light Weight Chord Library 1.0                 *
 *  CopyRight(C) Yoshihide Matsumoto IDEON WorkingGroup 2003,2004  *
 *      matsumoto333@yahoo.co.jp (http://www.matchan.mydns.jp)     *
 *                                                                 *
 * Implementation of chord (Distributed Hash Table)                *
 * This program is distributed under GPL                           *
 * Light Weight Chord Library comes with ABSOLUTELY NO WARRANTY.   *
 * This is free software, and you are welcome to redistribute it   *
 * under certain conditions; read `COPYING' for details.           *
 *******************************************************************/

#include <stdio.h>
#include <stdlib.h>

#include "id_list.h"
#include "misc.h"

//-  Queue---Address1->Address2->Address3
//
void id_init(IDLIST *pnew){
  //listの初期化デフォルト値の設定

  pnew->id = 0;
  return;
}


//-昇順に並ぶようにインサート
IDLIST *id_insert(IDLIST **phead, int id){

   IDLIST *plist, *pnew, *plist_bak;
   plist = *phead;
   
   //エラー処理
   if(id == 0){
     log(WARNING, "id_insert\n");
     return NULL;
   }

   pnew = (IDLIST *)malloc(sizeof(IDLIST));
   id_init(pnew);
   
   pnew->id = id;
   
   //１個目のリストを生成する場合   
   if(*phead == NULL){
      pnew->prev = NULL;
      pnew->next = NULL;
      *phead = pnew;
      return pnew;
   }
   

   //idまで進める
   while(plist != NULL && plist->id <= id){
     plist_bak = plist;
     plist = plist->next;
   }


   
   if(*phead == plist){
     //先頭に追加
     pnew->prev = NULL;
     pnew->next = plist;
     plist->prev = pnew;
     *phead = pnew;
     
   }else{
     
     //plist_bakの次、中間に追加する場合
     if(plist != NULL){
       plist_bak->next = pnew;
       pnew->prev = plist_bak;
       
       pnew->next = plist;
       plist->prev = pnew;
       
     }else{
       //最後の場合
       plist_bak->next = pnew;
       pnew->prev = plist_bak;
       
       pnew->next = NULL;
       
     }
   }

   return pnew;
}

//リストから指定されたポインタのリストを削除
IDLIST *id_delete(IDLIST **phead, IDLIST *pdel){


  IDLIST *plist;

  //リストが１つの場合
  if(pdel->prev == NULL && pdel->next == NULL){
    free(pdel);
    *phead = NULL;
    return NULL;
  }

  //リストが先頭の場合
  if(pdel->prev == NULL){
    pdel->next->prev = NULL;
    plist = pdel->next;
    free(pdel);
    *phead = plist;
    return plist;
  }

  //リストが最後尾の場合
  if(pdel->next == NULL){
    pdel->prev->next = NULL;
    free(pdel);
    return NULL;
  }

  //リストが間の場合
  plist = pdel->next;
  pdel->prev->next = pdel->next;
  pdel->next->prev = pdel->prev;
  free(pdel);

  //削除した次のリストを返す
  return plist;


}


//リストからKEYを元に削除
IDLIST *id_delete_key(IDLIST **phead, int id){

   IDLIST *plist, *pbak;
   plist = *phead;
   
   while( plist != NULL && plist->id < id){
      plist = plist->next;
   }
   
   while( plist != NULL && plist->id == id){
     //削除した次のリストを返す。ない場合はNULL
     plist = id_delete(phead, plist);
   }
   
   //削除した次のリストを返す
   return plist;
}



//リストからキーの値がいくつ存在するか検索する
//ヒットしない場合は0を返す
IDLIST *id_search(IDLIST *plist, int id){
  
  IDLIST *list_local;
  list_local = plist;
   

  while(list_local != NULL && list_local->id < id){
    list_local = list_local->next;
  }
  
  if(list_local != NULL && list_local->id == id){
    return list_local;
  }
  
  
  return NULL;

}


//リストの数を調べる
int id_size(IDLIST *plist){

   int count;
   IDLIST *list_local;
   list_local = plist;

   count = 0;
   while(list_local != NULL){
      count ++;
      list_local = list_local->next;
   }
   
   return count;

}

//リストの一覧表示、デバッグ用
void id_print(IDLIST **plist){

   int count;
   char buf[32];
   count=0;
   IDLIST *list_local;
   list_local = *plist;
   
   while(list_local != NULL){

     log(NOTICE, "%d:ID=%u\n", count, list_local->id);
     count++;

     list_local = list_local->next;
   }


}
















