400 lines
9.9 KiB
C++
400 lines
9.9 KiB
C++
/***************************************************************************
|
|
objects_list.h - description
|
|
-------------------
|
|
begin : Fri Mar 5 2004
|
|
copyright : (C) 2004 by David Rokhvarg
|
|
email : davidr@sangoma.com
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* 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. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#ifndef OBJECTS_LIST_H
|
|
#define OBJECTS_LIST_H
|
|
|
|
#define DBG_OBJ_LIST 0
|
|
|
|
enum LIST_ACTION_RETURN_CODE{
|
|
|
|
LIST_ACTION_OK=1,
|
|
LIST_INSERTION_FAILED_ELEMENT_EXIST,
|
|
LIST_INSERTION_FAILED_GENERAL_ERROR
|
|
};
|
|
|
|
#include "list_element.h"
|
|
#include "list_element_chan_def.h"
|
|
|
|
|
|
/**
|
|
*@author David Rokhvarg
|
|
*/
|
|
|
|
class objects_list {
|
|
|
|
unsigned int size;
|
|
list_element* head;
|
|
list_element* tail;
|
|
|
|
public:
|
|
void remove_all_elements()
|
|
{
|
|
Debug(DBG_OBJ_LIST, ("remove_all_elements()\n"));
|
|
list_element* tmp;
|
|
|
|
while((tmp = remove_from_tail()) != NULL){
|
|
|
|
switch(tmp->get_element_type())
|
|
{
|
|
case CHAN_DEF_LIST_ELEMENT:
|
|
delete (list_element_chan_def*)tmp;
|
|
break;
|
|
|
|
default:
|
|
Debug(1, ("remove_all_elements() - deleting 'list_element' of unknown type: %d!!\n",
|
|
tmp->get_element_type()));
|
|
delete tmp;
|
|
break;
|
|
}
|
|
}
|
|
Debug(DBG_OBJ_LIST, ("remove_all_elements()- End\n"));
|
|
|
|
size = 0;
|
|
tail = NULL;
|
|
head = NULL;
|
|
}
|
|
|
|
//public:
|
|
|
|
objects_list()
|
|
{
|
|
Debug(DBG_OBJ_LIST, ("objects_list::objects_list()\n"));
|
|
|
|
size = 0;
|
|
tail = NULL;
|
|
head = NULL;
|
|
}
|
|
|
|
~objects_list()
|
|
{
|
|
Debug(DBG_OBJ_LIST, ("objects_list::~objects_list()\n"));
|
|
remove_all_elements();
|
|
}
|
|
|
|
//insert using insertion sort, so largest element will be always at the head,
|
|
//smallest at the tail.
|
|
int insert(list_element* new_element)
|
|
{
|
|
int rc;
|
|
|
|
Debug(DBG_OBJ_LIST, ("objects_list::insert()\n"));
|
|
|
|
rc = real_insert(new_element);
|
|
|
|
#if 0
|
|
//for debugging display content after each insertion.
|
|
display_contents_of_list();
|
|
#endif
|
|
|
|
return rc;
|
|
}
|
|
|
|
void display_contents_of_list()
|
|
{
|
|
printf("------display_contents_of_list()-----------\n");
|
|
list_element_chan_def* tmp = (list_element_chan_def*)get_first();
|
|
while(tmp != NULL){
|
|
printf("comparator: %s\n", tmp->get_comparator());
|
|
tmp = (list_element_chan_def*)get_next_element(tmp);
|
|
}
|
|
printf("-------------------------------------------\n");
|
|
}
|
|
|
|
int real_insert(list_element* new_element)
|
|
{
|
|
Debug(DBG_OBJ_LIST, ("objects_list::real_insert()\n"));
|
|
|
|
new_element->reset();
|
|
|
|
//special case - list is empty
|
|
if(tail == NULL){
|
|
Debug(DBG_OBJ_LIST, ("special case - list is empty\n"));
|
|
tail = head = new_element;
|
|
|
|
size++;
|
|
|
|
Debug(DBG_OBJ_LIST, ("size:%d\n", size));
|
|
return LIST_ACTION_OK;
|
|
}
|
|
|
|
list_element* tmp_element = tail;
|
|
|
|
while(tmp_element != NULL){
|
|
|
|
if(tmp_element->compare(new_element) < 0){
|
|
|
|
list_element* next_element = get_next_element(tmp_element);
|
|
|
|
//check the next element greater than the new one.
|
|
if( next_element != NULL){
|
|
|
|
if(next_element->compare(new_element) > 0){
|
|
//this works because the list is *always* kept in order
|
|
insert_after_element(tmp_element, new_element);
|
|
return LIST_ACTION_OK;
|
|
}else{
|
|
//go to next
|
|
}
|
|
|
|
}else{
|
|
//it is the last element insert after it.
|
|
Debug(DBG_OBJ_LIST, ("inserting after last element\n"));
|
|
head = new_element;
|
|
insert_after_element(tmp_element, new_element);
|
|
return LIST_ACTION_OK;
|
|
}
|
|
|
|
}else if(tmp_element->compare(new_element) == 0){
|
|
Debug(DBG_OBJ_LIST, ("attempting to insert existing element %s!!\n",
|
|
tmp_element->get_comparator()));
|
|
return LIST_INSERTION_FAILED_ELEMENT_EXIST;
|
|
|
|
}else if(tmp_element->compare(new_element) > 0){
|
|
|
|
insert_before_element(tmp_element, new_element);
|
|
return LIST_ACTION_OK;
|
|
}
|
|
|
|
tmp_element = get_next_element(tmp_element);
|
|
}//while()
|
|
|
|
Debug(DBG_OBJ_LIST, ("insert() failer!!\n"));
|
|
return LIST_INSERTION_FAILED_GENERAL_ERROR;
|
|
}
|
|
|
|
list_element* get_next_element(list_element* element)
|
|
{
|
|
Debug(DBG_OBJ_LIST, ("objects_list::get_next_element()\n"));
|
|
|
|
return (list_element*)element->next;
|
|
}
|
|
|
|
|
|
list_element* get_previous_element(list_element* element)
|
|
{
|
|
Debug(DBG_OBJ_LIST, ("objects_list::get_previous_element()\n"));
|
|
|
|
return (list_element*)element->previous;
|
|
}
|
|
|
|
void insert_after_element(list_element* element, list_element* new_element)
|
|
{
|
|
Debug(DBG_OBJ_LIST, ("objects_list::insert_after_element()\n"));
|
|
Debug(DBG_OBJ_LIST, ("element: %s, new_element: %s\n",
|
|
element->get_comparator(), new_element->get_comparator() ));
|
|
|
|
new_element->reset();
|
|
|
|
new_element->next = element->next;
|
|
|
|
if(new_element->next != NULL){
|
|
((list_element*)new_element->next)->previous = new_element;
|
|
}
|
|
|
|
element->next = new_element;
|
|
|
|
new_element->previous = element;
|
|
|
|
size++;
|
|
|
|
Debug(DBG_OBJ_LIST, ("insert_after_element(): size:%d\n", size));
|
|
}
|
|
|
|
void insert_before_element(list_element* element, list_element* new_element)
|
|
{
|
|
Debug(DBG_OBJ_LIST, ("objects_list::insert_before_element()\n"));
|
|
Debug(DBG_OBJ_LIST, ("element: %s, new_element: %s\n",
|
|
element->get_comparator(), new_element->get_comparator() ));
|
|
|
|
new_element->reset();
|
|
|
|
new_element->next = element;
|
|
|
|
new_element->previous = element->previous;
|
|
|
|
if(new_element->previous != NULL){
|
|
((list_element*)new_element->previous)->next = new_element;
|
|
}
|
|
element->previous = new_element;
|
|
|
|
//special case inserting before the first element
|
|
if(tail == element){
|
|
tail = new_element;
|
|
}
|
|
|
|
size++;
|
|
Debug(DBG_OBJ_LIST, ("insert_before_element(): size:%d\n", size));
|
|
}
|
|
|
|
list_element* get_first()
|
|
{
|
|
Debug(DBG_OBJ_LIST, ("objects_list::get_first()\n"));
|
|
|
|
return tail;
|
|
}
|
|
|
|
list_element* get_last()
|
|
{
|
|
Debug(DBG_OBJ_LIST, ("objects_list::get_last()\n"));
|
|
|
|
return head;
|
|
}
|
|
|
|
unsigned int get_size()
|
|
{
|
|
return size;
|
|
}
|
|
|
|
//returns pointer to the smallest element,
|
|
//removes it from the list.
|
|
list_element* remove_from_tail()
|
|
{
|
|
if(tail == NULL){
|
|
Debug(DBG_OBJ_LIST, ("remove_from_tail(): list is empty.\n"));
|
|
return NULL;
|
|
}
|
|
|
|
list_element* tmp = tail;
|
|
list_element* next = (list_element*)tmp->next;
|
|
|
|
tail = next;
|
|
if(tail != NULL){
|
|
tail->previous = NULL;
|
|
}else{
|
|
Debug(DBG_OBJ_LIST, ("remove_from_tail(): removed last element.\n"));
|
|
head = NULL;
|
|
}
|
|
|
|
size--;
|
|
Debug(DBG_OBJ_LIST, ("remove_from_tail(): size: %d\n", size));
|
|
return tmp;
|
|
}
|
|
|
|
//returns pointer to the largest element,
|
|
//removes it from the list.
|
|
list_element* remove_from_head()
|
|
{
|
|
if(head == NULL){
|
|
Debug(DBG_OBJ_LIST, ("remove_from_head(): list is empty.\n"));
|
|
return NULL;
|
|
}
|
|
|
|
list_element* tmp = head;
|
|
list_element* previous = (list_element*)tmp->previous;
|
|
|
|
head = previous;
|
|
if(head != NULL){
|
|
head->next = NULL;
|
|
}else{
|
|
Debug(DBG_OBJ_LIST, ("remove_from_head(): removed last element.\n"));
|
|
tail = NULL;
|
|
}
|
|
|
|
size--;
|
|
Debug(DBG_OBJ_LIST, ("remove_from_head(): size: %d\n", size));
|
|
return tmp;
|
|
}
|
|
|
|
//returns pointer to the element containing 'comparator',
|
|
//removes the element from the list.
|
|
list_element* remove_element(char* comparator)
|
|
{
|
|
Debug(DBG_OBJ_LIST, ("remove_element(): searching for comparator: %s\n", comparator));
|
|
|
|
list_element* tmp = find_element(comparator);
|
|
if(tmp == NULL){
|
|
//no such element
|
|
return NULL;
|
|
}
|
|
|
|
list_element* previous = (list_element*)tmp->previous;
|
|
list_element* next = (list_element*)tmp->next;
|
|
|
|
if(previous != NULL){
|
|
previous->next = next;
|
|
}else{
|
|
//element at the tail is being deleted
|
|
tail = next;
|
|
if(next != NULL){
|
|
next->previous = NULL;
|
|
}
|
|
}
|
|
|
|
if(next != NULL){
|
|
next->previous = previous;
|
|
}else{
|
|
//element at the head is being deleted
|
|
head = previous;
|
|
if(previous != NULL){
|
|
previous->next = NULL;
|
|
}
|
|
}
|
|
|
|
size--;
|
|
|
|
if(size == 0){
|
|
head = NULL;
|
|
tail = NULL;
|
|
}
|
|
return tmp;
|
|
}
|
|
|
|
//returns pointer to the element containing 'comparator',
|
|
//if found
|
|
list_element* find_element(char* comparator)
|
|
{
|
|
Debug(DBG_OBJ_LIST, ("find_element(char* comparator): searching for comparator: %s\n",
|
|
comparator));
|
|
|
|
list_element* tmp = get_first();
|
|
|
|
while(tmp != NULL){
|
|
if(tmp->compare(comparator) == 0){
|
|
Debug(DBG_OBJ_LIST, ("find_element(): found searched element in the list %s\n", comparator));
|
|
return tmp;
|
|
}
|
|
tmp = get_next_element(tmp);
|
|
}
|
|
|
|
Debug(DBG_OBJ_LIST, ("find_element(): DID NOT found in the list %s!!\n", comparator));
|
|
return NULL;
|
|
}
|
|
/*
|
|
list_element* find_element(int comparator)
|
|
{
|
|
Debug(DBG_OBJ_LIST, ("find_element(int comparator): searching for comparator: %d\n",
|
|
comparator));
|
|
|
|
list_element* tmp = get_first();
|
|
|
|
while(tmp != NULL){
|
|
if(tmp->compare(comparator) == 0){
|
|
Debug(DBG_OBJ_LIST, ("find_element(): found searched element in the list %s\n", comparator));
|
|
return tmp;
|
|
}
|
|
tmp = get_next_element(tmp);
|
|
}
|
|
|
|
Debug(DBG_OBJ_LIST, ("find_element(): DID NOT found in the list %d!!\n", comparator));
|
|
return NULL;
|
|
}
|
|
*/
|
|
};
|
|
|
|
#endif
|