#ifndef ALREADY_INCLUDED_2006_LIBD__LIST_HH
#define ALREADY_INCLUDED_2006_LIBD__LIST_HH
#include "libd.hh"
#define for_list(X,iterator,list) for (ptr<List_Iterator<X> > iterator = (list)->get_first(); iterator->has_more(); iterator->advance())
#define for_list_backwards(X,iterator,list) for (ptr<List_Iterator<X> > iterator = (list)->get_last(); iterator->has_more(); iterator->retreat())
namespace dmp
{
template<class X>
class List_Node;
template<class X>
class List_Iterator;
template<class X>
class List : private Single
{
rtti_same(List);
POOL1;
friend class List_Node<X>;
friend class List_Iterator<X>;
private:
ptr<List_Node<X> > private_first;
ptr<List_Node<X> > private_last;
int private_length; dmp::string private_name;
private:
List(const List& list);
List& operator = (const List&);
public:
ptr<List> clone_shallow()
{
ptr<List<X> > p = List<X>::ctor();
for_list (X, it, this)
{
p->add_element(it->get_data());
}
return p;
}
ptr<List<X> > clone_deep()
{
ptr<List<X> > p = List<X>::ctor(private_name);
ASSERT(p->get_length() == 0);
int count = 0;
for_list (X, it, this)
{
ptr<X> px = it->get_data()->clone_deep();
p->add_element(px);
count++;
ASSERT_INFO(p->get_length() == count,
dmp::string() + "p->get_length()=" + p->get_length() + ", count=" + count);
}
return p;
}
void delete_all()
{
for_list (X, n, this)
{
n->delete_current();
}
assert(private_length == 0);
assert(private_first == null);
assert(private_last == null);
}
private:
List(dmp::string list_name) : Single(DCODE_LIST)
{
private_length = 0;
private_name = list_name;
}
public:
static ptr<List<X> > ctor(dmp::string name)
{
return new List<X>(name);
}
static ptr<List<X> > ctor()
{
return new List<X>("no name");
}
private:
template <class T> friend class ptr;
~List()
{
if (this == null)
{
return;
}
ptr<List_Node<X> > n_next = null;
for (ptr<List_Node<X> > n = private_first; n != null; n = n_next)
{
n_next = n->private_next;
n->delete_node();
}
#ifdef DAVINS_IO_ONLINE
ASSERT_INFO(private_length == 0, dmp::string() + "private_length=" + private_length);
#else
ASSERT(private_length == 0);
#endif
{
}
}
public:
ptr<List_Iterator<X> > get_element_at(int i)
{
ASSERT(this != null);
if (i < private_length/2)
{
int count = 0;
for (ptr<List_Node<X> > n = private_first; n != null; n = n->private_next)
{
if (count == i)
{
return List_Iterator<X>::ctor(n.operator->());
}
count++;
}
}
else
{
int count = private_length-1;
for (ptr<List_Node<X> > n = private_last; n != null; n = n->private_previous)
{
if (count == i)
{
return List_Iterator<X>::ctor(n.operator->());
}
count--;
}
}
ERROR(dmp::string() + "No such list element: " + i + ", get_length()=" + private_length);
}
ptr<List_Iterator<X> > get_first() const {
return List_Iterator<X>::ctor(private_first.get_ptr());
}
ptr<List_Iterator<X> > get_last() const {
return List_Iterator<X>::ctor(private_last.get_ptr());
}
int get_length() const
{
ASSERT(this != null);
return private_length;
}
dmp::string get_name() const
{
return private_name;
}
ptr<List<X> > add_to_start(const ptr<X>& x)
{
ASSERT(this != null);
ASSERT(&x != null);
ASSERT(x != null);
ptr<List_Node<X> > n = List_Node<X>::ctor();
n->private_data = x;
n->private_next = private_first;
n->private_previous = null;
n->private_owner = this;
if (private_first != null)
{
private_first->private_previous = n;
}
private_first = n;
if (private_last == null)
{
private_last = n;
}
private_length++;
return this;
}
ptr<List<X> > add_to_end(const ptr<X>& x)
{
ASSERT(this != null);
ASSERT(&x != null);
ptr<List_Node<X> > n = List_Node<X>::ctor();
n->private_data = x;
n->private_next = null;
n->private_previous = private_last;
n->private_owner = this;
if (private_last != null)
{
private_last->private_next = n;
}
if (private_first == null)
{
private_first = n;
}
private_last = n;
private_length++;
return this;
}
void reverse()
{
ASSERT(this != null);
ptr<List_Node<X> > n_next = null;
for (ptr<List_Node<X> > n = private_first; n != null; n=n_next)
{
n_next = n->private_next;
ptr<List_Node<X> > tmp = n->private_previous;
n->private_previous = n->private_next;
n->private_next = tmp;
}
ptr<List_Node<X> > tmp = private_first;
private_first = private_last;
private_last = tmp;
}
ptr<List<X> > add_list(const ptr<List<X> >& list)
{
ASSERT(this != null);
ASSERT(&list != null);
if (list != null)
{
for_list (X,n,list)
{
add_to_end(n);
}
}
return this;
}
ptr<List<X> > add_element(const ptr<X>& x)
{
ASSERT(this != null);
ASSERT(&x != null);
add_to_end(x);
return this;
}
bool OK()
{
#ifdef DAVINS_IO_ONLINE
assert(this != null);
if (this == null)
{
return true;
}
dmp::string_buffer sb;
int error_count = 0;
{
if (private_first == null)
{
if (private_last != null)
{
}
}
else
{
if (private_first->private_previous != null)
{
error_count++;
sb << "(" << error_count << ") private_first->private_previous != null\n";
}
}
}
{
if (private_last == null)
{
if (private_first != null)
{
}
}
else
{
if (private_last->private_next != null)
{
error_count++;
sb << "(" << error_count << ") private_last->private_next != null\n";
}
}
}
{
ptr<List_Node<X> > n = private_first;
if (n != null)
{
for (; n->private_next != null; n=n->private_next)
{
}
if (n != private_last)
{
error_count++;
sb << "(" << error_count << ") Calculated last (" << n->private_data << ") ";
sb << "does not agree with last element of list (";
sb << private_last << ")\n";
}
}
}
{
ptr<List_Node<X> > n = private_last;
if (n != null)
{
for (; n->private_previous != null; n=n->private_previous)
{
}
if (n != private_first)
{
error_count++;
sb << "(" << error_count << ") Calculated first (" << n->private_data << ") ";
sb << "does not agree with first element of list (";
sb << private_first << ")\n";
}
}
}
{
bool ok = true;
for (ptr<List_Node<X> > n = this->private_first; n != null; n=n->private_next)
{
if (n->private_owner != this) {
ok = false;
break;
}
}
for (ptr<List_Node<X> > n = this->private_last; n != null; n=n->private_previous)
{
if (n->private_owner != this)
{
ok = false;
break;
}
}
if (!ok)
{
error_count++;
sb << "(" << error_count << ") Some list element(s) do not have the correct owner field!\n";
}
}
{
int calculated_length_forward = 0;
for (ptr<List_Node<X> > n = this->private_first; n != null; n=n->private_next)
{
calculated_length_forward++;
}
if (calculated_length_forward != private_length)
{
error_count++;
sb << "(" << error_count << ") Calculated length forward (" << calculated_length_forward << ") ";
sb << "does not match list length (" << private_length << ")\n";
}
}
{
int calculated_length_backward = 0;
for (ptr<List_Node<X> > n = this->private_last; n != null; n=n->private_previous)
{
calculated_length_backward++;
}
if (calculated_length_backward != private_length)
{
error_count++;
sb << "(" << error_count << ") Calculated length backward (" << calculated_length_backward << ") ";
sb << "does not match list length (" << private_length << ")\n";
}
}
if (error_count != 0)
{
dmp::cout << '\n';
dmp::cout << "*** Error(s) in List<X>::OK() method:\n";
dmp::cout << "------------------------------------------\n";
dmp::cout << sb;
}
return error_count == 0;
#else
return true;
#endif
}
#ifdef DAVINS_IO_ONLINE
friend dmp::Writer& operator << (dmp::Writer& w, const List<X>& list)
{
ASSERT(&w != null);
ASSERT(&list != null);
w << '(' << "List";
for_list (X,it,&list)
{
w << ' ' << it->get_data();
}
w << ')';
return w;
}
friend dmp::Reader& operator >> (dmp::Reader& r, List<X>& list)
{
ASSERT(&r != null);
ASSERT(&list != null);
ASSERT(list.get_length() == 0);
r >> '(' >> "List";
while (!r.looking_at(')'))
{
if (r.looking_at("null"))
{
X* x = null;
list.add_to_end(x);
r.next_token(); }
else
{
ptr<X> x = X::ctor();
r >> *x.get_ptr();
list.add_to_end(x);
}
}
r >> ')';
return r;
}
#endif
ptr<List_Iterator<X> > find(bool pred(const ptr<X>& p))
{
for_list (X,n,this)
{
if (pred(n->get_data()))
{
return n;
}
}
return null;
}
static ptr<List_Iterator<X> > find_element_eq(const ptr<List_Iterator<X> > start, const ptr<X>& key)
{
ASSERT(&key != null);
for (ptr<List_Iterator<X> > it = start->clone(); it->has_more(); it->advance())
{
if (it->get_data() == key)
{
return it;
}
}
return null;
}
ptr<List_Iterator<X> > find_element_equal(int start, const ptr<X>& key)
{
int count = 0;
for_list (X, it, this)
{
if (count >= start)
{
if (*it->get_data() == *key.get_ptr())
{
return it;
}
}
count++;
}
return null;
}
friend ptr<List_Iterator<X> > find_element_equal(const ptr<List_Iterator<X> >& start, const ptr<X>& key)
{
ASSERT(&start != null);
ASSERT(&key != null);
for (ptr<List_Iterator<X> > it = start->clone(); it->has_more(); it->advance())
{
if (*it->get_data() == *key.get_ptr())
{
return it;
}
}
return null;
}
void remove_element_eq(const ptr<X>& s)
{
ASSERT(this != null);
assert(&s != null); for_list (X,n,this)
{
if (n->get_data() == s)
{
n->delete_current();
}
}
}
friend ptr<List<X> > quicksort(const ptr<List<X> >& list, int compare(const ptr<X>& x1, const ptr<X>& x2))
{
if (list->get_length() < 2)
{
return list;
}
ptr<X> mid = list->get_element_at(list->get_length() / 2)->get_data();
ptr<List<X> > smaller_than = List<X>::ctor(list->private_name);
ptr<List<X> > equal_to = List<X>::ctor(list->private_name);
ptr<List<X> > greater_than = List<X>::ctor(list->private_name);
if (compare == null)
{
should_never_happen();
return list;
}
{
for_list (X, n, list)
{
ptr<X> t = n->get_data();
int c = compare(t,mid);
if (c < 0)
{
smaller_than->add_element(t);
}
else if (c > 0)
{
greater_than->add_element(t);
}
else
{
equal_to->add_element(t);
}
}
}
{
if (smaller_than->get_length() > 1)
{
smaller_than = quicksort(smaller_than, compare);
}
if (greater_than->get_length() > 1)
{
greater_than = quicksort(greater_than, compare);
}
}
{
ptr<List<X> > result = List<X>::ctor(list->private_name);
for_list (X,n,smaller_than)
{
result->add_element(n->get_data());
}
for_list (X,n,equal_to)
{
result->add_element(n->get_data());
}
for_list (X,n,greater_than)
{
result->add_element(n->get_data());
}
return result;
}
}
friend bool operator == (const List<X>& list1, const List<X>& list2)
{
if (list1.get_length() != list2.get_length())
{
return false;
}
ptr<List_Iterator<X> > it1 = list1.get_first();
ptr<List_Iterator<X> > it2 = list2.get_first();
for (;;)
{
if (*it1->get_data() != *it2->get_data())
{
return false;
}
it1->advance();
it2->advance();
if (!it1->has_more() && !it2->has_more())
{
return true;
}
else if (!it1->has_more() || !it2->has_more())
{
should_never_happen();
return false;
}
}
return true;
}
friend bool operator != (const List<X>& list1, const List<X>& list2)
{
return !(list1 == list2);
}
};
}
#include "_List_Node.hh"
#include "_List_Iterator.hh"
#endif