Files
2014-08-09 08:46:27 -07:00

279 lines
6.2 KiB
C

/*****************************************************************************
** $Source$
**
** $Revision$
**
** $Date$
**
** More info: http://www.bluemsx.com
**
** Copyright (C) 2003-2013 Daniel Vik, Akop Karapetyan
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
******************************************************************************
*/
#include "ArrayList.h"
#include <stdlib.h>
struct ArrayListNode
{
struct ArrayListNode *next;
void *object;
int managed;
};
typedef struct ArrayListNode ArrayListNode;
struct ArrayList
{
ArrayListNode *head;
ArrayListNode *tail;
int size;
};
struct ArrayListIterator
{
const ArrayListNode *current;
const ArrayList *list;
};
static ArrayListNode *arrayListCreateNode(void *object, int managed);
static ArrayListNode *arrayListDestroyNode(ArrayListNode *node);
static ArrayListNode *arrayListFindNodeAtIndex(const ArrayList *list, int elementAt);
ArrayList *arrayListCreate()
{
ArrayList *list = (ArrayList *)malloc(sizeof(ArrayList));
list->head = NULL;
list->tail = NULL;
list->size = 0;
return list;
}
void arrayListDestroy(ArrayList *list)
{
ArrayListNode *node = list->head;
while (node)
node = arrayListDestroyNode(node);
free(list);
}
static ArrayListNode *arrayListFindNodeAtIndex(const ArrayList *list, int elementAt)
{
int index = 0;
ArrayListNode *current;
if (elementAt < 0 || elementAt >= list->size)
return NULL;
for (current = list->head; current; current = current->next, index++)
if (index == elementAt)
return current;
return NULL;
}
static ArrayListNode *arrayListCreateNode(void *object, int managed)
{
ArrayListNode *node = (ArrayListNode *)malloc(sizeof(ArrayListNode));
if (node)
{
node->next = NULL;
node->object = object;
node->managed = managed;
}
return node;
}
static ArrayListNode *arrayListDestroyNode(ArrayListNode *node)
{
ArrayListNode *next;
if (!node)
return NULL;
next = node->next;
if (node->managed)
free(node->object);
free(node);
return next; // Return the next node
}
int arrayListInsert(ArrayList *list, int insertAt, void *object, int managed)
{
ArrayListNode *newNode;
if (insertAt < 0 || insertAt > list->size)
return 0;
newNode = arrayListCreateNode(object, managed);
if (!newNode)
return 0;
if (insertAt == list->size)
{
// Append
if (list->tail)
list->tail->next = newNode;
list->tail = newNode;
}
else if (insertAt == 0)
{
// Prepend
newNode->next = list->head;
list->head = newNode;
}
else
{
ArrayListNode *nextNode;
ArrayListNode *precedingNode;
// Find the node previous to the location we're inserting
precedingNode = arrayListFindNodeAtIndex(list, insertAt - 1);
if (!precedingNode)
{
arrayListDestroyNode(newNode);
return 0;
}
// Get a reference to the current next node
nextNode = precedingNode->next;
// Insert the element
precedingNode->next = newNode;
newNode->next = nextNode;
}
if (!list->head)
list->head = newNode;
if (!list->tail)
list->tail = newNode;
list->size++;
return 1;
}
int arrayListPrepend(ArrayList *list, void *object, int managed)
{
return arrayListInsert(list, 0, object, managed);
}
int arrayListAppend(ArrayList *list, void *object, int managed)
{
return arrayListInsert(list, list->size, object, managed);
}
int arrayListRemove(ArrayList *list, int removeAt)
{
if (removeAt < 0 || removeAt >= list->size)
return 0;
if (removeAt == 0)
{
// Remove head
ArrayListNode *next = arrayListDestroyNode(list->head);
if (list->tail == list->head)
list->tail = NULL;
list->head = next;
}
else
{
ArrayListNode *nodeToRemove;
ArrayListNode *precedingNode;
// Find the node previous to the one we're removing
precedingNode = arrayListFindNodeAtIndex(list, removeAt - 1);
if (!precedingNode)
return 0;
nodeToRemove = precedingNode->next;
if (!nodeToRemove)
return 0;
precedingNode->next = nodeToRemove->next;
if (list->tail == nodeToRemove)
list->tail = precedingNode;
arrayListDestroyNode(nodeToRemove);
}
list->size--;
return 1;
}
int arrayListGetSize(const ArrayList *list)
{
return list->size;
}
void *arrayListGetObject(const ArrayList *list, int elementAt)
{
ArrayListNode *node = arrayListFindNodeAtIndex(list, elementAt);
if (!node)
return NULL;
return node->object;
}
ArrayListIterator *arrayListCreateIterator(const ArrayList *list)
{
ArrayListIterator *iterator = (ArrayListIterator *)malloc(sizeof(ArrayListIterator));
if (iterator)
{
iterator->list = list;
iterator->current = list->head;
}
return iterator;
}
void arrayListDestroyIterator(ArrayListIterator *iterator)
{
free(iterator);
}
void *arrayListIterate(ArrayListIterator *iterator)
{
void *object;
if (!iterator->current)
return NULL;
object = iterator->current->object;
iterator->current = iterator->current->next;
return object;
}
int arrayListCanIterate(const ArrayListIterator *iterator)
{
return (iterator->current != NULL);
}