File: cpw_linkedlist.c/***************************************************************************/
/* */
/* cpw_linkedlist.c */
/* */
/* Cpw's linked list. General purpose linked list routines. */
/* */
/* Copyright 2001-2002 by */
/* Jim Mathies, */
/* */
/* This file is part of the Cpw project, and may only be used, */
/* modified, and distributed under the terms of the Cpw project */
/* license. By continuing to use, modify, or distribute this file */
/* you indicate that you have read the license and understand and */
/* accept it fully. */
/* */
/* File Platform: cross */
/* */
/***************************************************************************/
#include "cpw_linkedlist.h"
/* init of list data structure */
void
ll_initList( LinkedListData * lld )
{
lld->idcount = 1;
lld->baseElement = null;
}
/* deletes a list's contents. returns the number of objects collected */
uint_32
ll_deleteList( LinkedListData * lld )
{
uint_32 killcount = 0;
if ( lld == null ) return 0;
if ( lld->baseElement == null ) return 0;
killcount = 0;
/* clean up the list elements */
le_cleanUp( lld->baseElement, &killcount );
/* free our base element */
le_freeElement( &lld->baseElement );
lld->idcount = 1;
lld->baseElement = null;
return killcount++;
}
/* create and init a list */
LinkedListData *
ll_createList( void )
{
LinkedListData * p;
p = (LinkedListData*) cpwmalloc( sizeof( LinkedListData ) );
if ( p == null ) return null;
ll_initList( p );
return p;
}
/* delete and free a list pointer */
void
ll_freeList( LinkedListData ** lld )
{
if ( lld == null ) return;
if ( *lld == null ) return;
ll_deleteList( *lld );
cpwfree( *lld );
*lld = null;
}
/* returns id of element or 0 on error */
uint_32
ll_addStr( LinkedListData * lld, pStr string )
{
LinkedElement * le = le_initStr( string, lld->idcount );
if ( le == null ) return 0;
if ( lld->baseElement == null ) {
lld->baseElement = le;
} else {
le_linkUp( lld->baseElement, le );
}
lld->idcount++;
return lld->idcount-1;
}
/* returns id of element or 0 on error */
uint_32
ll_addString( LinkedListData * lld, char* string )
{
LinkedElement * le = le_initString( string, lld->idcount );
if ( le == null ) return 0;
if ( lld->baseElement == null ) {
lld->baseElement = le;
} else {
le_linkUp( lld->baseElement, le );
}
lld->idcount++;
return lld->idcount-1;
}
/* returns id of element or 0 on error */
uint_32
ll_addFloat64( LinkedListData * lld, float_64 number )
{
LinkedElement * le = le_initFloat64( number, lld->idcount );
if ( le == null ) return 0;
if ( lld->baseElement == null ) {
lld->baseElement = le;
} else {
le_linkUp( lld->baseElement, le );
}
lld->idcount++;
return lld->idcount-1;
}
/* returns id of element or 0 on error */
uint_32
ll_addInt32( LinkedListData * lld, int_32 number )
{
LinkedElement * le = le_initInt32( number, lld->idcount );
if ( le == null ) return 0;
if ( lld->baseElement == null ) {
lld->baseElement = le;
} else {
le_linkUp( lld->baseElement, le );
}
lld->idcount++;
return lld->idcount-1;
}
/* returns id of element or 0 on error */
uint_32
ll_addVoid( LinkedListData * lld, void * p )
{
LinkedElement * le = le_initVoid( p, lld->idcount );
if ( le == null ) return 0;
if ( lld->baseElement == null ) {
lld->baseElement = le;
} else {
le_linkUp( lld->baseElement, le );
}
lld->idcount++;
return lld->idcount-1;
}
/* returns pStr or null if not found */
bool
ll_getString( LinkedListData * lld, pStr* string, uint_32 id )
{
LinkedElement * le;
if ( lld->baseElement == null ) return false;
le = le_seek( lld->baseElement, id );
setStr( string, le_getString( le ) );
return true;
}
/* returns void* pointer or null if not found */
bool
ll_getVoid( LinkedListData * lld, void** pdata, uint_32 id )
{
LinkedElement * le;
if ( lld->baseElement == null ) return false;
le = le_seek( lld->baseElement, id );
*pdata = le_getVoid( le );
return true;
}
/* returns bool indicating success or failure, fills string with value if found */
bool
ll_popString( LinkedListData * lld, pStr * string )
{
LinkedElement * le;
pStr tmp;
if ( lld->baseElement == null ) return false;
le = le_lastOne( lld->baseElement );
if ( le == null ) return false;
tmp = le_getString( le );
if ( tmp == null ) return false;
setStr( string, tmp );
le = le_unLink( lld->baseElement, null, le_getId( le ) );
if ( le == lld->baseElement ) lld->baseElement = null;
le_freeElement( &le );
lld->idcount = 1;
return true;
}
bool
ll_popFloat64( LinkedListData * lld, float_64 * number )
{
LinkedElement * le;
if ( lld->baseElement == null ) return false;
le = le_lastOne( lld->baseElement );
if ( le == null ) return false;
*number = le_getFloat64( le );
le = le_unLink( lld->baseElement, null, le_getId( le ) );
if ( le == lld->baseElement ) lld->baseElement = null;
le_freeElement( &le );
lld->idcount = 1;
return true;
}
bool
ll_popInt32( LinkedListData * lld, int_32 * number )
{
LinkedElement * le;
if ( lld->baseElement == null ) return false;
le = le_lastOne( lld->baseElement );
if ( le == null ) return false;
*number = le_getInt32( le );
le = le_unLink( lld->baseElement, null, le_getId( le ) );
if ( le == lld->baseElement ) lld->baseElement = null;
le_freeElement( &le );
lld->idcount = 1;
return true;
}
bool
ll_setVoid( LinkedListData * lld, uint_32 id, void* p )
{
LinkedElement * le;
if ( lld->baseElement == null ) return false;
if ( !( le = le_seek( lld->baseElement, id ) ) )
return false;
le_setVoid( le, p );
return true;
}
bool
ll_deleteElement( LinkedListData * lld, uint_32 id )
{
LinkedElement * le = null;
if ( lld->baseElement == null ) return false;
le = le_unLink( lld->baseElement, null, id );
if ( le == lld->baseElement ) lld->baseElement = null;
if ( le != null ) {
le_freeElement( &le );
return true;
}
return false;
}
int_32
ll_getLength( LinkedListData * lld )
{
uint_32 count = 0;
if ( lld->baseElement == null ) return 0;
le_countUp( lld->baseElement, &count );
return count;
}
bool
ll_initIterate( LinkedListData * lld )
{
if ( lld->baseElement == null ) return false;
le_initIterate( lld->baseElement );
return true;
}
LinkedElement *
ll_getNext( LinkedListData * lld )
{
if ( lld->baseElement == null ) return 0;
return le_getNext( lld->baseElement );
}
LinkedElement *
ll_getElement( LinkedListData * lld, uint_32 id )
{
if ( lld->baseElement == null ) return 0;
return le_seek( lld->baseElement, id );
}
uint_32
ll_linkUp( LinkedListData * lld, LinkedElement* le )
{
if ( le == null ) return 0;
le_setId( le, lld->idcount );
lld->idcount++;
if ( lld->baseElement == null )
lld->baseElement = le;
else
le_linkUp( lld->baseElement, le );
return lld->idcount;
}
/* unlink an element. does not delete the element. */
bool
ll_unLink( LinkedListData * lld, uint_32 id )
{
LinkedElement * le;
le = null;
if ( lld->baseElement != null )
le = le_unLink( lld->baseElement, null, id );
/* not found */
if ( le == null )
return false;
if ( le == lld->baseElement ) lld->baseElement = null;
lld->idcount = 1;
return true;
}
/* flip the list over into a new list. lld must have been created
with ll_createList(). It is iterated, deleted, freed here and then replaced. */
bool
ll_flipList( LinkedListData ** lld )
{
LinkedElement * le;
LinkedListData * plist;
if ( lld == null ) return false;
if ( *lld == null ) return false;
if ( ll_getLength( *lld ) <= 0 ) return false;
plist = ll_createList();
ll_initList( plist );
/* flip into new stack */
while ( le = le_lastOne( (*lld)->baseElement ) ) {
switch ( le->etype ) {
case Element_pStr:
ll_addStr( plist, le->e.e_pstr );
break;
case Element_Float64:
ll_addFloat64( plist, le->e.e_float_32 );
break;
case Element_Int32:
ll_addInt32( plist, le->e.e_int_32 );
break;
case Element_Void:
ll_addVoid( plist, le->e.e_pvoid );
break;
}
ll_unLink( *lld, le_getId( le ) );
le_freeElement( &le );
}
ll_freeList( lld );
*lld = plist;
return true;
}