00001
00027
00028
00029
00030
00031
00032 #ifndef __Lst__
00033 #define __Lst__
00034
00035 #include "assert.hpp"
00036
00037 template <class C> class LstData;
00038
00039
00040 template <class C>
00041 class Lst
00042 {
00043 public:
00044
00045 Lst ();
00046 Lst (const Lst&);
00047 Lst (const C& head, const Lst& tail);
00048 explicit Lst (const C& t);
00049 explicit Lst (LstData<C>*);
00050 ~Lst ();
00051 void operator = (const Lst& rhs);
00052
00053
00054
00055 void append (const Lst&);
00056
00057
00058 bool isEmpty () const;
00059 bool isNonEmpty () const;
00060 const C& head () const;
00061 const C& second () const;
00062 const Lst& tail () const;
00063 void pop ();
00064 bool operator == (const Lst& rhs) const;
00065 void makeEmpty ();
00066
00067
00068 int length () const;
00069 bool member (const C elem) const;
00070 void push (C elem);
00071 void reverse (Lst& result) const;
00072 void reverse (Lst& result, const Lst& appendTo) const;
00073 void copy (Lst& to) const;
00074
00075 protected:
00076
00077 LstData<C>* _data;
00078 };
00079
00080
00081
00082 template <class C>
00083 class LstData
00084 {
00085 public:
00086 LstData ();
00087
00088 inline LstData (const C& t, const Lst<C>& ts)
00089 :
00090 _counter (1),
00091 _head (t),
00092 _tail (ts)
00093 {
00094 TRACER( "LstData::LstData" );
00095 }
00096
00097 inline explicit LstData (const C& t)
00098 :
00099 _counter (1),
00100 _head (t),
00101 _tail ((LstData<C>*)0)
00102 {
00103 TRACER( "LstData::LstData" );
00104 }
00105
00106 inline ~LstData ()
00107 {
00108 TRACER( "LstData::~LstData" );
00109
00110 ASS (_counter == 0);
00111 }
00112
00113 inline void ref ()
00114 {
00115 ASS (this);
00116
00117 _counter++;
00118 }
00119
00120
00121 inline void deref ()
00122 {
00123 ASS (this);
00124 ASS (_counter > 0);
00125
00126 _counter--;
00127 if (_counter == 0) {
00128 delete this;
00129 }
00130 }
00131
00132 inline const C& head () const
00133 {
00134 ASS (this);
00135 ASS (_counter > 0);
00136
00137 return _head;
00138 }
00139
00140 inline const Lst<C>& tail () const
00141 {
00142 ASS (this);
00143 ASS (_counter > 0);
00144
00145 return _tail;
00146 }
00147
00148 private:
00149
00150 unsigned _counter;
00151 C _head;
00152 Lst<C> _tail;
00153 };
00154
00155
00156
00157
00158 template <class C>
00159 class Iterator
00160 {
00161 public:
00162 inline explicit Iterator (const Lst<C>& lst)
00163 :
00164 _list (lst)
00165 {
00166 }
00167
00168 inline bool more () const
00169 {
00170 return _list.isNonEmpty();
00171 }
00172
00173 inline C next ()
00174 {
00175 ASS( more() );
00176
00177 C result (_list.head());
00178 _list.pop ();
00179
00180 return result;
00181 }
00182
00183 inline void reset (const Lst<C>& lst)
00184 {
00185 _list = lst;
00186 }
00187
00188 private:
00189 Lst<C> _list;
00190 };
00191
00192
00193
00194
00195 template <class C>
00196 inline
00197 Lst<C>::Lst ()
00198 :
00199 _data (0)
00200 {
00201 }
00202
00203
00204 template <class C>
00205 inline
00206 Lst<C>::~Lst ()
00207 {
00208 if (_data) {
00209 _data->deref ();
00210 }
00211 }
00212
00213
00214
00215
00216 template <class C>
00217 inline
00218 Lst<C>::Lst (const Lst& ts)
00219 :
00220 _data (ts._data)
00221 {
00222 if (_data) {
00223 _data->ref ();
00224 }
00225 }
00226
00227
00228
00229
00230 template <class C>
00231 inline
00232 Lst<C>::Lst (LstData<C>* d)
00233 :
00234 _data (d)
00235 {
00236 if (d) {
00237 d->ref ();
00238 }
00239 }
00240
00241
00242
00243
00244 template <class C>
00245 inline
00246 Lst<C>::Lst (const C &hd, const Lst& tl)
00247 :
00248 _data (new LstData<C> (hd,tl))
00249 {
00250 }
00251
00252
00253
00254
00255 template <class C>
00256 inline
00257 Lst<C>::Lst (const C &hd)
00258 :
00259 _data (new LstData<C> (hd))
00260 {
00261 }
00262
00263
00264 template <class C>
00265 inline
00266 bool Lst<C>::operator == (const Lst& rhs) const
00267 {
00268 return _data == rhs._data;
00269 }
00270
00271
00272 template <class C>
00273 inline
00274 bool Lst<C>::isEmpty () const
00275 {
00276 return _data == 0;
00277 }
00278
00279
00280 template <class C>
00281 inline
00282 bool Lst<C>::isNonEmpty () const
00283 {
00284 return _data != 0;
00285 }
00286
00287
00288 template <class C>
00289 inline
00290 const C& Lst<C>::head () const
00291 {
00292 return _data->head ();
00293 }
00294
00295
00296 template <class C>
00297 inline
00298 const C& Lst<C>::second () const
00299 {
00300 return _data->tail().head();
00301 }
00302
00303
00304 template <class C>
00305 inline
00306 const Lst<C>& Lst<C>::tail () const
00307 {
00308 return _data->tail();
00309 }
00310
00311
00312
00313
00314
00315 template <class C>
00316 void Lst<C>::pop ()
00317 {
00318 ASS (_data);
00319
00320 LstData<C>* dtl = tail()._data;
00321 if (! dtl) {
00322 _data->deref();
00323 _data = 0;
00324 return;
00325 }
00326
00327 dtl->ref ();
00328 _data->deref ();
00329 _data = dtl;
00330
00331 }
00332
00333
00334
00335
00336 template <class C>
00337 bool Lst<C>::member (const C elem) const
00338 {
00339 Iterator<C> it (*this);
00340 while (it.more()) {
00341 if (it.next() == elem) {
00342 return true;
00343 }
00344 }
00345
00346 return false;
00347 }
00348
00349
00350 template <class C>
00351 inline
00352 void Lst<C>::push (C elem)
00353 {
00354 *this = Lst (elem,*this);
00355 }
00356
00357
00358 template <class C>
00359 inline
00360 void Lst<C>::makeEmpty ()
00361 {
00362 if (_data) {
00363 _data->deref ();
00364 _data = 0;
00365 }
00366 }
00367
00368
00369 template <class C>
00370 void Lst<C>::operator = (const Lst& t)
00371 {
00372 if (t._data) {
00373 t._data->ref ();
00374 }
00375
00376 if (_data) {
00377 _data->deref ();
00378 }
00379
00380 _data = t._data;
00381 }
00382
00383
00384
00385
00386
00387
00388 template <class C>
00389 void Lst<C>::append (const Lst& to)
00390 {
00391 if (isEmpty()) {
00392 *this = to;
00393 return;
00394 }
00395
00396 Lst tl (tail());
00397 tl.append (to);
00398 *this = Lst (head(),tl);
00399 }
00400
00401
00402
00403
00404 template <class C>
00405 int Lst<C>::length () const
00406 {
00407 int len = 0;
00408
00409 for (LstData<C>* d = _data; d; d = d->tail()._data) {
00410 len ++;
00411 }
00412
00413 return len;
00414 }
00415
00416
00417
00418
00419 template <class C>
00420 void Lst<C>::reverse (Lst& result, const Lst& appendTo) const
00421 {
00422 TRACER("LST::reverse/3");
00423
00424 Lst rev (appendTo);
00425
00426 Iterator<C> it (*this);
00427 while (it.more()) {
00428 rev.push (it.next());
00429 }
00430
00431 result = rev;
00432 }
00433
00434
00435
00436
00437 template <class C>
00438 inline
00439 void Lst<C>::reverse (Lst& result) const
00440 {
00441 TRACER("LST::reverse/2");
00442
00443 Lst empty;
00444 reverse (result,empty);
00445 }
00446
00447
00448
00449
00450 template <class C>
00451 inline
00452 void Lst<C>::copy (Lst& to) const
00453 {
00454 TRACER("Lst::copy");
00455
00456 if (isEmpty()) {
00457 return;
00458 }
00459
00460 to = Lst (head());
00461 tail().copy (const_cast<Lst&>(to.tail()));
00462 }
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593 #endif // __Lst__
00594