/* * (C) 1998-1999 Murat Deligonul * * 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 "linkedlist.h" #include #include #include #include "debug.h" /* * Optional last argument returns idx of last found node. */ __list_core::node * __list_core::find_by_idx(int idx, int * pt) const { int target = 0; for (node * current = _first; current; current = current->next, target++) { if (target == idx) { if (pt) *pt = target; return current; } } if (pt) *pt = target; return NULL; } /** * Construct a new list */ __list_core::__list_core(void) { _last = _first = NULL; num_nodes = 0; mod_count = 0; } /* Remove all elements */ void __list_core::clear(void) { while (_first) remove(0); } /* * Add an element to the end of the list */ int __list_core::add(void * data) { return add(size(), data); node * n = new node; assert(data != 0); if (!_first) _first = n; if (_last) _last->next = n; n->data = data; n->prev = _last; n->next = NULL; _last = n; return (++num_nodes); } /* * Insert at arbitrary position. * arguments: * data -- what to add * idx -- where to add: * 0 - beginning of list * 0- [size()-1] - somewhere in the list * size() -- at the end of the list. * * We become the element at that position, and slide * the element currently there up one spot * * Return: new number of elements (0 on error) */ int __list_core::add(int idx, void * data) { assert(data != 0); assert(idx <= size()); assert(idx >= 0); node * current; if (idx == size()) /* Want to add to the end */ current = 0; else current = find_by_idx(idx); node * n = new node; n->data = data; if (current) { /* Any valid position, besides last */ if (current->prev) current->prev->next = n; n->prev = current->prev; n->next = current; current->prev = n; } else { /* Adding to end (or adding the first to an empty list) */ n->prev = _last; n->next = NULL; if (_last) _last->next = n; } if (!n->prev) _first = n; if (!n->next) _last = n; assert(_first); assert(_last); mod_count++; DEBUG("__list_core::add() -- [%p] for %p -- size: %d\n", this, data, num_nodes + 1); return (++num_nodes); } /* * Get element[idx], but do not remove it. * Use remove() if you want to remove it. */ void * __list_core::get(int idx) { node * n = find_by_idx(idx); return n ? n->data : NULL; } /* * Get element[idx] and remove it */ void * __list_core::remove(int idx) { node * n = find_by_idx(idx); if (!n) return NULL; return remove(n); } void * __list_core::remove(node * n) { void * d = n->data; if (n->prev) n->prev->next = n->next; if (n->next) n->next->prev = n->prev; if (!n->prev) _first = n->next; if (!n->next) _last = n->prev; delete n; num_nodes--; mod_count++; return d; } bool __list_core::remove(void * data) { assert(data != 0); for (node * n = _first; n; n = n->next) if (n->data == data) { remove(n); DEBUG("__list_core::remove() -- [%p] for %p -- new size: %d\n", this, data, num_nodes); return true; } DEBUG("__list_core:remove() -- [%p] couldn't find %p!!\n", this, data); return false; } void * __list_iter::next() { assert(mod_count == list->mod_count); assert(current); if (current) { last_returned = current; current = current->next; return last_returned->data; } return 0; } void * __list_iter::remove() { assert(last_returned); assert(mod_count == list->mod_count); void * d = last_returned->data; DEBUG("__list_iter::remove(): [%p] current: %p last_returned: %p\n", this, current, last_returned); list->remove(last_returned); mod_count++; last_returned = 0; assert(mod_count == list->mod_count); return d; } /* * Remove a string from a list. */ int strlist_remove(strlist * list, const char * str) { list_iterator i(list); while (i.has_next()) { char * s = i.next(); if (!strcasecmp(str, s)) { delete[] s; i.remove(); return 1; } } return 0; }