// ////////////////////////////////////////////////////////
// Copyright (1994) Columbia University
// Department of Biochemistry and Molecular Biophysics
//
// Author: Weider Chang, Ph.D
// ///////////////////////////////////////////////////////

#ifndef _WDCOBJLIST_H
#define _WDCOBJLIST_H

#include "wobject.h"
#include <objc/list.h>

// Supplemental procedure for struct objc_list defined in list.h of libobjc.a

static inline void
list_insert_element(struct objc_list** list, void* elem, int n)
{
  while(0<n--)
    {
      if (*list) list=&((*list)->tail);
      else break;
    }
  (*list)=list_cons(elem, (*list));
}

static inline void*
list_replace_element(struct objc_list** list, void* elem, int n)
{
  void * rtl;
  while(0<n--)
    {
      if (*list) list=&((*list)->tail);
      else 
	{
	  (*list)=list_cons(0, 0);
	  break;
	}
    }
  rtl=(*list)->head;
  (*list)->head=elem;
  return rtl;
}

// The following two functions are replacements of the functions in 
// list.h of the Objective-c run-time library.

// Remove the element at the head by replacing it by its successor 
// replacement of list_remove_head

static inline void
list_remove_head_node(struct objc_list** list)
{
  if ((*list)->tail)
    {
      // original implementation.

      // struct objc_list* tail = (*list)->tail; /* fetch next */
      // *(*list) = *tail; 		/* copy next to list head */
      // free(tail); 			/* free next */

	struct objc_list* garbage=(*list);
	(*list)=(*list)->tail;
	free(garbage);
 
    }
  else				/* only one element in list */
    {
      free (*list);
      (*list) = 0;
    }
}


// this is a replacement for K.K. Thorup's list_remove_elem (in list.h)

static inline void
list_remove_element(struct objc_list** list, void* elem)
{
  while (*list) 
    {
      if ((*list)->head == elem) list_remove_head_node(list);
      
      // the problem was K.K.T did not validate the (*list) before
      // the assigment of "list=&((*list)->tail); It cause segmentation fault
      // when (*list->head) is the last or the only element of the list.
	
      if (*list) list = &((*list)->tail);
    }
}


static inline void*
list_remove_nth_node(struct objc_list** list, int n)
{
  void * rntl=0;
  while (0<n--) if (*list) list=&((*list)->tail);
  if (*list) 
    {
      rntl=(*list)->head;
      list_remove_head_node(list);
    }
  return rntl;
}



//
// contain WDCStarDataBlk, WDCItemAssocValue or WDCString
//

@interface WDCObjList : WDCObject 
{
  @private
    struct objc_list * _list;
  //  WDCObjList * _next;
}

- init:(struct objc_list *)list;
- (int)getListLength;
- getNth:(int)n;
- remove:obj;
- (BOOL)isExist:obj;
- add:obj;
- getNextOf:obj;
- getPreviousOf:obj;
- (struct objc_list*)getObjcList;
- (struct objc_list*)getNextObjcList;
- insertNth:(int)n with:obj;
// - setNextObjList:obj;

@end

@interface WDCSortedObjList: WDCObjList 
{
  @private
    SEL _aSel; // the sorting critaria.
}

- init:(struct objc_list*)list with:(SEL)aSel;
- add:obj;
- getObjectAssoKey:key;

@end

// 
// Contain a list of WDCStarDataBlks. The default deta block is data_file_name,
// which contains the input filename in _blockName and 0 or more data item.
//
// global_ data items should be expended or overrided in all data blocks     
//

@interface WDCStarFile : WDCSortedObjList 
{
  @private
    WDCStarFile * _next;
}

- init;
- (const char *)getFileName;
- getDataBlk:(const char*)blkname;
- getNext;
- setNext:file;
- add:file;

@end

#endif


