source: libcfa/src/bits/queue.hfa@ 6b33e89

Last change on this file since 6b33e89 was 6b33e89, checked in by Peter A. Buhr <pabuhr@…>, 5 months ago

change backquote call to regular call

  • Property mode set to 100644
File size: 5.5 KB
RevLine 
[5e82d56]1#pragma once
2
[7d4ce2a]3#include "bits/collection.hfa"
[5e82d56]4
[9536761]5// A Queue(T) is a Collection(T) defining the ordering that nodes are returned by drop() in the same order from those
6// added by add(). T must be a public descendant of uColable.
7
8// The implementation is a typical singly-linked list, except the next field of the last element points to itself
9// instead of being null.
10
[fd54fef]11forall( T & | { T *& Next ( T * ); } ) {
[5e82d56]12 struct Queue {
13 inline Collection; // Plan 9 inheritance
14 T * last; // last element, or 0 if queue is empty.
15 };
16
[c407434e]17 static inline {
[5e82d56]18 // wrappers to make Collection have T
[a78c3ff]19 T & head( Queue(T) & q ) with( q ) {
20 return *(T *)head( (Collection &)q );
[5e82d56]21 } // post: empty() & head() == 0 | !empty() & head() in *q
22
23 void ?{}( Queue(T) &, const Queue(T) & ) = void; // no copy
24 Queue(T) & ?=?( const Queue(T) & ) = void; // no assignment
25
[6b33e89]26 void ?{}( Queue(T) & q ) {
[5e82d56]27 ((Collection &)q){};
[6b33e89]28 q.last = 0p;
[5e82d56]29 } // post: empty()
30
[6b33e89]31 T & tail( Queue(T) & q ) {
32 return *q.last;
[5e82d56]33 }
34
[10b5970]35 T * succ( Queue(T) & q, T * n ) { // pre: *n in *q
36 #ifdef __CFA_DEBUG__
[a5a67ab8]37 if ( ! listed( n ) ) abort( "(Queue &)%p.succ( %p ) : Node is not on a list.", &q, n );
[10b5970]38 #else
39 (void) q;
40 #endif // __CFA_DEBUG__
[58870e6b]41 return (Next( n ) == n) ? 0p : Next( n );
[5e82d56]42 } // post: n == tail() & succ(n) == 0 | n != tail() & *succ(n) in *q
43
[a3a76ea]44 T & addHead( Queue(T) & q, T & n ) with( q ) {
[7c1144b]45 #ifdef __CFA_DEBUG__
[a78c3ff]46 if ( listed( &n ) ) abort( "(Queue &)%p.addHead( %p ) : Node is already on another list.", &q, &n );
[7c1144b]47 #endif // __CFA_DEBUG__
[6b33e89]48 if ( q.last ) {
[58870e6b]49 Next( &n ) = &head( q );
[a78c3ff]50 q.root = &n;
[5e82d56]51 } else {
[a78c3ff]52 root = last = &n;
[58870e6b]53 Next( &n ) = &n; // last node points to itself
[5e82d56]54 }
[a3a76ea]55 return n;
[5e82d56]56 }
57
[a3a76ea]58 T & addTail( Queue(T) & q, T & n ) with( q ) {
[7c1144b]59 #ifdef __CFA_DEBUG__
[a78c3ff]60 if ( listed( &n ) ) abort( "(Queue &)%p.addTail( %p ) : Node is already on another list.", &q, &n );
[7c1144b]61 #endif // __CFA_DEBUG__
[6b33e89]62 if ( q.last ) Next( last ) = &n;
[a78c3ff]63 else root = &n;
64 last = &n;
[58870e6b]65 Next( &n ) = &n; // last node points to itself
[a3a76ea]66 return n;
[5e82d56]67 }
68
[a3a76ea]69 T & add( Queue(T) & q, T & n ) with( q ) {
70 return addTail( q, n );
[5e82d56]71 }
72
[a78c3ff]73 T & dropHead( Queue(T) & q ) with( q ) {
[a5a67ab8]74 T & t = head( q );
[5e82d56]75 if ( root ) {
[accc5dbb]76 root = Next( (T *)root );
[a5a67ab8]77 if ( &head( q ) == &t ) {
[5e82d56]78 root = last = 0p; // only one element
79 }
[58870e6b]80 Next( &t ) = 0p;
[5e82d56]81 }
[a5a67ab8]82 return t;
[5e82d56]83 }
84
[a78c3ff]85 T & drop( Queue(T) & q ) with( q ) {
[5e82d56]86 return dropHead( q );
87 }
88
[a3a76ea]89 T & remove( Queue(T) & q, T & n ) with( q ) { // O(n)
[7c1144b]90 #ifdef __CFA_DEBUG__
[a78c3ff]91 if ( ! listed( (Colable &)n ) ) abort( "(Queue &)%p.remove( %p ) : Node is not on a list.", &q, &n );
[7c1144b]92 #endif // __CFA_DEBUG__
[58870e6b]93 T * prev = 0p;
94 T * curr = (T *)root;
[d9b7b66]95 for () {
[58870e6b]96 if ( &n == curr ) { // found => remove
[a5a67ab8]97 if ( (T *)root == &n ) {
[5e82d56]98 dropHead( q );
[a5a67ab8]99 } else if ( last == &n ) {
[58870e6b]100 last = prev;
101 Next( last ) = last;
[5e82d56]102 } else {
103 Next( prev ) = Next( curr );
104 }
[58870e6b]105 Next( &n ) = 0p;
[5e82d56]106 break;
107 }
108 // not found => error
[7c1144b]109 #ifdef __CFA_DEBUG__
[58870e6b]110 if ( curr == last ) abort( "(Queue &)%p.remove( %p ) : Node is not in list.", &q, &n );
[7c1144b]111 #endif // __CFA_DEBUG__
[58870e6b]112 prev = curr;
113 curr = Next( curr );
[5e82d56]114 }
[a3a76ea]115 return n;
[5e82d56]116 } // post: ! listed( n )
117
[9536761]118 T & dropTail( Queue(T) & q ) with( q ) { // O(n)
[a78c3ff]119 T & n = tail( q );
120 return &n ? remove( q, n ), n : *0p;
[5e82d56]121 }
122
123 // Transfer the "from" list to the end of queue sequence; the "from" list is empty after the transfer.
124 void transfer( Queue(T) & q, Queue(T) & from ) with( q ) {
125 if ( empty( from ) ) return; // "from" list empty ?
126 if ( empty( q ) ) { // "to" list empty ?
127 root = from.root;
128 } else { // "to" list not empty
[58870e6b]129 Next( last ) = &head( from );
[5e82d56]130 }
131 last = from.last;
132 from.root = from.last = 0p; // mark "from" list empty
133 }
134
135 // Transfer the "from" list up to node "n" to the end of queue list; the "from" list becomes the list after node "n".
136 // Node "n" must be in the "from" list.
[a78c3ff]137 void split( Queue(T) & q, Queue(T) & from, T & n ) with( q ) {
[7c1144b]138 #ifdef __CFA_DEBUG__
[a78c3ff]139 if ( ! listed( (Colable &)n ) ) abort( "(Queue &)%p.split( %p ) : Node is not on a list.", &q, &n );
[7c1144b]140 #endif // __CFA_DEBUG__
[5e82d56]141 Queue(T) to;
142 to.root = from.root; // start of "to" list
[a78c3ff]143 to.last = &n; // end of "to" list
[58870e6b]144 from.root = Next( &n ); // start of "from" list
[a5a67ab8]145 if ( &n == &head( from ) ) { // last node in list ?
[5e82d56]146 from.root = from.last = 0p; // mark "from" list empty
147 } else {
[58870e6b]148 Next( &n ) = &n; // fix end of "to" list
[5e82d56]149 }
150 transfer( q, to );
151 }
152 } // distribution
153} // distribution
154
[fd54fef]155forall( T & | { T *& Next ( T * ); } ) {
[5e82d56]156 struct QueueIter {
157 inline ColIter; // Plan 9 inheritance
[c407434e]158 };
[5e82d56]159
[c407434e]160 static inline {
[5e82d56]161 void ?{}( QueueIter(T) & qi ) with( qi ) {
162 ((ColIter &)qi){};
163 } // post: curr == 0p
164
[9536761]165 // create an iterator active in queue q
[5e82d56]166 void ?{}( QueueIter(T) & qi, Queue(T) & q ) with( qi ) {
[a78c3ff]167 curr = &head( q );
[5e82d56]168 } // post: curr = {e in q}
169
[a78c3ff]170 void ?{}( QueueIter(T) & qi, T & start ) with( qi ) {
171 curr = &start;
[5e82d56]172 } // post: curr = {e in q}
173
[9536761]174 // make existing iterator active in queue q
[5e82d56]175 void over( QueueIter(T) & qi, Queue(T) & q ) with( qi ) {
[a78c3ff]176 curr = &head( q );
[5e82d56]177 } // post: curr = {e in q}
178
[9536761]179 bool ?|?( QueueIter(T) & qi, T && tp ) with( qi ) {
[5e82d56]180 if ( curr ) {
[3d0560d]181 &tp = Curr( qi );
[58870e6b]182 T * n = Next( Curr( qi ) );
[5e82d56]183 curr = (n == Curr( qi ) ) ? 0p : n;
[3d0560d]184 } else &tp = 0p;
185 return &tp != 0p;
[5e82d56]186 }
[9536761]187 // post: elts == null & !operator|(tp) | elts != null & *tp' in elts & elts' == elts - *tp & operator|(tp)
[5e82d56]188 } // distribution
189} // distribution
Note: See TracBrowser for help on using the repository browser.