home *** CD-ROM | disk | FTP | other *** search
- // This may look like C code, but it is really -*- C++ -*-
- /*
- Copyright (C) 1988 Free Software Foundation
- written by Doug Lea (dl@rocky.oswego.edu)
-
- This file is part of the GNU C++ Library. This library is free
- software; you can redistribute it and/or modify it under the terms of
- the GNU Library General Public License as published by the Free
- Software Foundation; either version 2 of the License, or (at your
- option) any later version. This library 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 Library General Public License for more details.
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free Software
- Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- #ifdef __GNUG__
- #pragma implementation
- #endif
- #include <builtin.h>
- #include "<T>.List.h"
-
- <T>ListNode Nil<T>ListNode;
-
- class init_Nil<T>ListNode
- {
- public:
- init_Nil<T>ListNode()
- {
- Nil<T>ListNode.tl = &Nil<T>ListNode;
- Nil<T>ListNode.ref = -1;
- }
- };
-
- static init_Nil<T>ListNode Nil<T>ListNode_initializer;
-
- <T>List& <T>List::operator = (<T>List& a)
- {
- reference(a.P);
- dereference(P);
- P = a.P;
- return *this;
- }
-
- <T> <T>List::pop()
- {
- <T> res = P->hd;
- <T>ListNode* tail = P->tl;
- reference(tail);
- dereference(P);
- P = tail;
- return res;
- }
-
- void <T>List::set_tail(<T>List& a)
- {
- reference(a.P);
- dereference(P->tl);
- P->tl = a.P;
- }
-
- <T>List <T>List::nth(int n)
- {
- for (<T>ListNode* p = P; n-- > 0; p = p->tl);
- reference(p);
- return <T>List(p);
- }
-
- <T>List <T>List::last()
- {
- <T>ListNode* p = P;
- if (p != &Nil<T>ListNode) while (p->tl != &Nil<T>ListNode) p = p->tl;
- reference(p);
- return <T>List(p);
- }
-
- void <T>List::append(<T>List& l)
- {
- <T>ListNode* p = P;
- <T>ListNode* a = l.P;
- reference(a);
- if (p != &Nil<T>ListNode)
- {
- while (p->tl != &Nil<T>ListNode) p = p->tl;
- p->tl = a;
- }
- else
- P = a;
- }
-
- int <T>List::length()
- {
- int l = 0;
- for (<T>ListNode* p = P; p != &Nil<T>ListNode; p = p->tl) ++l;
- return l;
- }
-
- <T>& <T>List::operator [] (int n)
- {
- for (<T>ListNode* p = P; n-- > 0; p = p->tl);
- return (p->hd);
- }
-
- int operator == (<T>List& x, <T>List& y)
- {
- <T>ListNode* a = x.P;
- <T>ListNode* b = y.P;
-
- for (;;)
- {
- if (a == &Nil<T>ListNode)
- return b == &Nil<T>ListNode;
- else if (b == &Nil<T>ListNode)
- return 0;
- else if (<T>EQ(a->hd, b->hd))
- {
- a = a->tl;
- b = b->tl;
- }
- else
- return 0;
- }
- }
-
-
- void <T>List::apply(<T>Procedure f)
- {
- for(<T>ListNode* p = P; p != &Nil<T>ListNode; p = p->tl)
- (*f)((p->hd));
- }
-
- void <T>List::subst(<T&> old, <T&> repl)
- {
- for(<T>ListNode* p = P; p != &Nil<T>ListNode; p = p->tl)
- if (<T>EQ(p->hd, old))
- p->hd = repl;
- }
-
- <T> <T>List::reduce(<T>Combiner f, <T&> base)
- {
- <T> r = base;
- for(<T>ListNode* p = P; p != &Nil<T>ListNode; p = p->tl)
- r = (*f)(r, (p->hd));
- return r;
- }
-
- int <T>List::position(<T&> targ)
- {
- int l = 0;
- <T>ListNode* p = P;
- for (;;)
- {
- if (p == &Nil<T>ListNode)
- return -1;
- else if (<T>EQ(p->hd, targ))
- return l;
- else
- {
- ++l;
- p = p->tl;
- }
- }
- }
-
- int <T>List::contains(<T&> targ)
- {
- <T>ListNode* p = P;
- for (;;)
- {
- if (p == &Nil<T>ListNode)
- return 0;
- else if (<T>EQ(p->hd, targ))
- return 1;
- else
- p = p->tl;
- }
- }
-
- <T>List <T>List::find(<T&> targ)
- {
- <T>ListNode* p = P;
- while (p != &Nil<T>ListNode && !<T>EQ(p->hd, targ))
- p=p->tl;
- reference(p);
- return <T>List(p);
- }
-
- Pix <T>List::seek(<T&> targ)
- {
- <T>ListNode* p = P;
- for (;;)
- {
- if (p == &Nil<T>ListNode)
- return 0;
- else if (<T>EQ(p->hd, targ))
- return Pix(p);
- else
- p = p->tl;
- }
- }
-
- int <T>List::owns(Pix i)
- {
- <T>ListNode* p = P;
- for (;;)
- {
- if (p == &Nil<T>ListNode)
- return 0;
- else if (Pix(p) == i)
- return 1;
- else
- p = p->tl;
- }
- }
-
- <T>List <T>List::find(<T>List& target)
- {
- <T>ListNode* targ = target.P;
- if (targ == &Nil<T>ListNode)
- return <T>List(targ);
-
- <T>ListNode* p = P;
- while (p != &Nil<T>ListNode)
- {
- if (<T>EQ(p->hd, targ->hd))
- {
- <T>ListNode* a = p->tl;
- <T>ListNode* t = targ->tl;
- for(;;)
- {
- if (t == &Nil<T>ListNode)
- {
- reference(p);
- return <T>List(p);
- }
- else if (a == &Nil<T>ListNode || !<T>EQ(a->hd, t->hd))
- break;
- else
- {
- a = a->tl;
- t = t->tl;
- }
- }
- }
- p = p->tl;
- }
- return <T>List(&Nil<T>ListNode);
- }
-
- int <T>List::contains(<T>List& target)
- {
- <T>ListNode* targ = target.P;
- if (targ == &Nil<T>ListNode)
- return 0;
-
- <T>ListNode* p = P;
- while (p != &Nil<T>ListNode)
- {
- if (<T>EQ(p->hd, targ->hd))
- {
- <T>ListNode* a = p->tl;
- <T>ListNode* t = targ->tl;
- for(;;)
- {
- if (t == &Nil<T>ListNode)
- return 1;
- else if (a == &Nil<T>ListNode || !<T>EQ(a->hd, t->hd))
- break;
- else
- {
- a = a->tl;
- t = t->tl;
- }
- }
- }
- p = p->tl;
- }
- return 0;
- }
-
- void <T>List::del(<T&> targ)
- {
- <T>ListNode* h = P;
-
- for (;;)
- {
- if (h == &Nil<T>ListNode)
- {
- P = h;
- return;
- }
- else if (<T>EQ(h->hd, targ))
- {
- <T>ListNode* nxt = h->tl;
- reference(nxt);
- dereference(h);
- h = nxt;
- }
- else
- break;
- }
-
- <T>ListNode* trail = h;
- <T>ListNode* p = h->tl;
- while (p != &Nil<T>ListNode)
- {
- if (<T>EQ(p->hd, targ))
- {
- <T>ListNode* nxt = p->tl;
- reference(nxt);
- dereference(p);
- trail->tl = nxt;
- p = nxt;
- }
- else
- {
- trail = p;
- p = p->tl;
- }
- }
- P = h;
- }
-
- void <T>List::del(<T>Predicate f)
- {
- <T>ListNode* h = P;
- for (;;)
- {
- if (h == &Nil<T>ListNode)
- {
- P = h;
- return;
- }
- else if ((*f)(h->hd))
- {
- <T>ListNode* nxt = h->tl;
- reference(nxt);
- dereference(h);
- h = nxt;
- }
- else
- break;
- }
-
- <T>ListNode* trail = h;
- <T>ListNode* p = h->tl;
- while (p != &Nil<T>ListNode)
- {
- if ((*f)(p->hd))
- {
- <T>ListNode* nxt = p->tl;
- reference(nxt);
- dereference(p);
- trail->tl = nxt;
- p = nxt;
- }
- else
- {
- trail = p;
- p = p->tl;
- }
- }
- P = h;
- }
-
- void <T>List::select(<T>Predicate f)
- {
- <T>ListNode* h = P;
- for (;;)
- {
- if (h == &Nil<T>ListNode)
- {
- P = h;
- return;
- }
- else if (!(*f)(h->hd))
- {
- <T>ListNode* nxt = h->tl;
- reference(nxt);
- dereference(h);
- h = nxt;
- }
- else
- break;
- }
- <T>ListNode* trail = h;
- <T>ListNode* p = h->tl;
- while (p != &Nil<T>ListNode)
- {
- if (!(*f)(p->hd))
- {
- <T>ListNode* nxt = p->tl;
- reference(nxt);
- dereference(p);
- trail->tl = nxt;
- p = nxt;
- }
- else
- {
- trail = p;
- p = p->tl;
- }
- }
- P = h;
- }
-
- void <T>List::reverse()
- {
- <T>ListNode* l = &Nil<T>ListNode;
- <T>ListNode* p = P;
- while (p != &Nil<T>ListNode)
- {
- <T>ListNode* nxt = p->tl;
- p->tl = l;
- l = p;
- p = nxt;
- }
- P = l;
- }
-
-
- <T>List copy(<T>List& x)
- {
- <T>ListNode* a = x.P;
- if (a == &Nil<T>ListNode)
- return <T>List(a);
- else
- {
- <T>ListNode* h = new<T>ListNode(a->hd);
- <T>ListNode* trail = h;
- for(a = a->tl; a != &Nil<T>ListNode; a = a->tl)
- {
- <T>ListNode* n = new<T>ListNode(a->hd);
- trail->tl = n;
- trail = n;
- }
- trail->tl = &Nil<T>ListNode;
- return <T>List(h);
- }
- }
-
-
- <T>List subst(<T&> old, <T&> repl, <T>List& x)
- {
- <T>ListNode* a = x.P;
- if (a == &Nil<T>ListNode)
- return <T>List(a);
- else
- {
- <T>ListNode* h = new <T>ListNode;
- h->ref = 1;
- if (<T>EQ(a->hd, old))
- h->hd = repl;
- else
- h->hd = a->hd;
- <T>ListNode* trail = h;
- for(a = a->tl; a != &Nil<T>ListNode; a = a->tl)
- {
- <T>ListNode* n = new <T>ListNode;
- n->ref = 1;
- if (<T>EQ(a->hd, old))
- n->hd = repl;
- else
- n->hd = a->hd;
- trail->tl = n;
- trail = n;
- }
- trail->tl = &Nil<T>ListNode;
- return <T>List(h);
- }
- }
-
- <T>List combine(<T>Combiner f, <T>List& x, <T>List& y)
- {
- <T>ListNode* a = x.P;
- <T>ListNode* b = y.P;
- if (a == &Nil<T>ListNode || b == &Nil<T>ListNode)
- return <T>List(&Nil<T>ListNode);
- else
- {
- <T>ListNode* h = new<T>ListNode((*f)(a->hd, b->hd));
- <T>ListNode* trail = h;
- a = a->tl;
- b = b->tl;
- while (a != &Nil<T>ListNode && b != &Nil<T>ListNode)
- {
- <T>ListNode* n = new<T>ListNode((*f)(a->hd, b->hd));
- trail->tl = n;
- trail = n;
- a = a->tl;
- b = b->tl;
- }
- trail->tl = &Nil<T>ListNode;
- return <T>List(h);
- }
- }
-
- <T>List reverse(<T>List& x)
- {
- <T>ListNode* a = x.P;
- if (a == &Nil<T>ListNode)
- return <T>List(a);
- else
- {
- <T>ListNode* l = new<T>ListNode(a->hd);
- l->tl = &Nil<T>ListNode;
- for(a = a->tl; a != &Nil<T>ListNode; a = a->tl)
- {
- <T>ListNode* n = new<T>ListNode(a->hd);
- n->tl = l;
- l = n;
- }
- return <T>List(l);
- }
- }
-
- <T>List append(<T>List& x, <T>List& y)
- {
- <T>ListNode* a = x.P;
- <T>ListNode* b = y.P;
- reference(b);
- if (a != &Nil<T>ListNode)
- {
- <T>ListNode* h = new<T>ListNode(a->hd);
- <T>ListNode* trail = h;
- for(a = a->tl; a != &Nil<T>ListNode; a = a->tl)
- {
- <T>ListNode* n = new<T>ListNode(a->hd);
- trail->tl = n;
- trail = n;
- }
- trail->tl = b;
- return <T>List(h);
- }
- else
- return <T>List(b);
- }
-
- void <T>List::prepend(<T>List& y)
- {
- <T>ListNode* b = y.P;
- if (b != &Nil<T>ListNode)
- {
- <T>ListNode* h = new<T>ListNode(b->hd);
- <T>ListNode* trail = h;
- for(b = b->tl; b != &Nil<T>ListNode; b = b->tl)
- {
- <T>ListNode* n = new<T>ListNode(b->hd);
- trail->tl = n;
- trail = n;
- }
- trail->tl = P;
- P = h;
- }
- }
-
- <T>List concat(<T>List& x, <T>List& y)
- {
- <T>ListNode* a = x.P;
- <T>ListNode* b = y.P;
- if (a != &Nil<T>ListNode)
- {
- <T>ListNode* h = new<T>ListNode(a->hd);
- <T>ListNode* trail = h;
- for(a = a->tl; a != &Nil<T>ListNode; a = a->tl)
- {
- <T>ListNode* n = new<T>ListNode(a->hd);
- trail->tl = n;
- trail = n;
- };
- for(;b != &Nil<T>ListNode; b = b->tl)
- {
- <T>ListNode* n = new<T>ListNode(b->hd);
- trail->tl = n;
- trail = n;
- }
- trail->tl = &Nil<T>ListNode;
- return <T>List(h);
- }
- else if (b != &Nil<T>ListNode)
- {
- <T>ListNode* h = new<T>ListNode(b->hd);
- <T>ListNode* trail = h;
- for(b = b->tl; b != &Nil<T>ListNode; b = b->tl)
- {
- <T>ListNode* n = new<T>ListNode(b->hd);
- trail->tl = n;
- trail = n;
- }
- trail->tl = &Nil<T>ListNode;
- return <T>List(h);
- }
- else
- return <T>List(&Nil<T>ListNode);
- }
-
- <T>List select(<T>Predicate f, <T>List& x)
- {
- <T>ListNode* a = x.P;
- <T>ListNode* h = &Nil<T>ListNode;
- while (a != &Nil<T>ListNode)
- {
- if ((*f)(a->hd))
- {
- h = new<T>ListNode(a->hd);
- <T>ListNode* trail = h;
- for(a = a->tl; a != &Nil<T>ListNode; a = a->tl)
- {
- if ((*f)(a->hd))
- {
- <T>ListNode* n = new<T>ListNode(a->hd);
- trail->tl = n;
- trail = n;
- }
- }
- trail->tl = &Nil<T>ListNode;
- break;
- }
- else
- a = a->tl;
- }
- return <T>List(h);
- }
-
- <T>List remove(<T>Predicate f, <T>List& x)
- {
- <T>ListNode* a = x.P;
- <T>ListNode* h = &Nil<T>ListNode;
- while (a != &Nil<T>ListNode)
- {
- if (!(*f)(a->hd))
- {
- h = new<T>ListNode(a->hd);
- <T>ListNode* trail = h;
- for(a = a->tl; a != &Nil<T>ListNode; a = a->tl)
- {
- if (!(*f)(a->hd))
- {
- <T>ListNode* n = new<T>ListNode(a->hd);
- trail->tl = n;
- trail = n;
- }
- }
- trail->tl = &Nil<T>ListNode;
- break;
- }
- else
- a = a->tl;
- }
- return <T>List(h);
- }
-
- <T>List remove(<T&> targ, <T>List& x)
- {
- <T>ListNode* a = x.P;
- <T>ListNode* h = &Nil<T>ListNode;
- while (a != &Nil<T>ListNode)
- {
- if (!(<T>EQ(a->hd, targ)))
- {
- h = new<T>ListNode(a->hd);
- <T>ListNode* trail = h;
- for(a = a->tl; a != &Nil<T>ListNode; a = a->tl)
- {
- if (!<T>EQ(a->hd, targ))
- {
- <T>ListNode* n = new<T>ListNode(a->hd);
- trail->tl = n;
- trail = n;
- }
- }
- trail->tl = &Nil<T>ListNode;
- break;
- }
- else
- a = a->tl;
- }
- return <T>List(h);
- }
-
- <T>List map(<T>Mapper f, <T>List& x)
- {
- <T>ListNode* a = x.P;
- <T>ListNode* h = &Nil<T>ListNode;
- if (a != &Nil<T>ListNode)
- {
- h = new<T>ListNode((*f)(a->hd));
- <T>ListNode* trail = h;
- for(a = a->tl; a != &Nil<T>ListNode; a = a->tl)
- {
- <T>ListNode* n = new<T>ListNode((*f)(a->hd));
- trail->tl = n;
- trail = n;
- }
- trail->tl = &Nil<T>ListNode;
- }
- return <T>List(h);
- }
-
-
- <T>List merge(<T>List& x, <T>List& y, <T>Comparator f)
- {
- <T>ListNode* a = x.P;
- <T>ListNode* b = y.P;
-
- if (a == &Nil<T>ListNode)
- {
- if (b == &Nil<T>ListNode)
- return <T>List(&Nil<T>ListNode);
- else
- return copy(y);
- }
- else if (b == &Nil<T>ListNode)
- return copy(x);
-
- <T>ListNode* h = new <T>ListNode;
- h->ref = 1;
- if ((*f)(a->hd, b->hd) <= 0)
- {
- h->hd = a->hd;
- a = a->tl;
- }
- else
- {
- h->hd = b->hd;
- b = b->tl;
- }
-
- <T>ListNode* r = h;
-
- for(;;)
- {
- if (a == &Nil<T>ListNode)
- {
- while (b != &Nil<T>ListNode)
- {
- <T>ListNode* n = new <T>ListNode;
- n->ref = 1;
- n->hd = b->hd;
- r->tl = n;
- r = n;
- b = b->tl;
- }
- r->tl = &Nil<T>ListNode;
- return <T>List(h);
- }
- else if (b == &Nil<T>ListNode)
- {
- while (a != &Nil<T>ListNode)
- {
- <T>ListNode* n = new <T>ListNode;
- n->ref = 1;
- n->hd = a->hd;
- r->tl = n;
- r = n;
- a = a->tl;
- }
- r->tl = &Nil<T>ListNode;
- return <T>List(h);
- }
- else if ((*f)(a->hd, b->hd) <= 0)
- {
- <T>ListNode* n = new <T>ListNode;
- n->ref = 1;
- n->hd = a->hd;
- r->tl = n;
- r = n;
- a = a->tl;
- }
- else
- {
- <T>ListNode* n = new <T>ListNode;
- n->ref = 1;
- n->hd = b->hd;
- r->tl = n;
- r = n;
- b = b->tl;
- }
- }
- }
-
- void <T>List::sort(<T>Comparator f)
- {
- // strategy: place runs in queue, merge runs until done
- // This is often very fast
-
- if (P == &Nil<T>ListNode || P->tl == &Nil<T>ListNode)
- return;
-
- int qlen = 250; // guess a good queue size, realloc if necessary
-
- <T>ListNode** queue = (<T>ListNode**)malloc(qlen * sizeof(<T>ListNode*));
-
- <T>ListNode* h = P;
- <T>ListNode* a = h;
- <T>ListNode* b = a->tl;
- int qin = 0;
-
- while (b != &Nil<T>ListNode)
- {
- if ((*f)(a->hd, b->hd) > 0)
- {
- if (h == a) // minor optimization: ensure runlen >= 2
- {
- h = b;
- a->tl = b->tl;
- b->tl = a;
- b = a->tl;
- }
- else
- {
- if (qin >= qlen)
- {
- qlen *= 2;
- queue = (<T>ListNode**)realloc(queue, qlen * sizeof(<T>ListNode*));
- }
- queue[qin++] = h;
- a->tl = &Nil<T>ListNode;
- h = a = b;
- b = b->tl;
- }
- }
- else
- {
- a = b;
- b = b->tl;
- }
- }
-
- int count = qin;
- queue[qin] = h;
- if (++qin >= qlen) qin = 0;
- int qout = 0;
-
- while (count-- > 0)
- {
- a = queue[qout];
- if (++qout >= qlen) qout = 0;
- b = queue[qout];
- if (++qout >= qlen) qout = 0;
-
- if ((*f)(a->hd, b->hd) <= 0)
- {
- h = a;
- a = a->tl;
- }
- else
- {
- h = b;
- b = b->tl;
- }
- queue[qin] = h;
- if (++qin >= qlen) qin = 0;
-
- for (;;)
- {
- if (a == &Nil<T>ListNode)
- {
- h->tl = b;
- break;
- }
- else if (b == &Nil<T>ListNode)
- {
- h->tl = a;
- break;
- }
- else if ((*f)(a->hd, b->hd) <= 0)
- {
- h->tl = a;
- h = a;
- a = a->tl;
- }
- else
- {
- h->tl = b;
- h = b;
- b = b->tl;
- }
- }
- }
- P = queue[qout];
- free(queue);
- }
-
- int <T>List::list_length()
- {
- <T>ListNode* fast = P;
- if (fast == &Nil<T>ListNode)
- return 0;
-
- <T>ListNode* slow = fast->tl;
- if (slow == &Nil<T>ListNode)
- return 1;
-
- fast = slow->tl;
- int n = 2;
-
- for (;;)
- {
- if (fast == &Nil<T>ListNode)
- return n;
- else if (fast->tl == &Nil<T>ListNode)
- return n+1;
- else if (fast == slow)
- return -1;
- else
- {
- n += 2;
- fast = fast->tl->tl;
- slow = slow->tl;
- }
- }
- }
-
- void <T>List::error(const char* msg)
- {
- (*lib_error_handler)("List", msg);
- }
-
- int <T>List::OK()
- {
- int v = P != 0; // have a node
- // check that all nodes OK, even if circular:
-
- <T>ListNode* fast = P;
- if (fast != &Nil<T>ListNode)
- {
- v &= fast->ref != 0;
- <T>ListNode* slow = fast->tl;
- v &= slow->ref != 0;
- if (v && slow != &Nil<T>ListNode)
- {
- fast = slow->tl;
- v &= fast->ref != 0;
- while (v)
- {
- if (fast == &Nil<T>ListNode)
- break;
- else if (fast->tl == &Nil<T>ListNode)
- break;
- else if (fast == slow)
- break;
- else
- {
- v &= fast->ref != 0 && slow->ref != 0;
- fast = fast->tl->tl;
- slow = slow->tl;
- }
- }
- }
- }
- if (!v) error ("invariant failure");
- return v;
- }
-