library of assembled shared sources

http://lass.cocamware.com

slist.inl

Go to the documentation of this file.
00001 /** @file
00002  *  @author Bram de Greve (bramz@users.sourceforge.net)
00003  *  @author Tom De Muer (tomdemuer@users.sourceforge.net)
00004  *
00005  *  *** BEGIN LICENSE INFORMATION ***
00006  *  
00007  *  The contents of this file are subject to the Common Public Attribution License 
00008  *  Version 1.0 (the "License"); you may not use this file except in compliance with 
00009  *  the License. You may obtain a copy of the License at 
00010  *  http://lass.sourceforge.net/cpal-license. The License is based on the 
00011  *  Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover 
00012  *  use of software over a computer network and provide for limited attribution for 
00013  *  the Original Developer. In addition, Exhibit A has been modified to be consistent 
00014  *  with Exhibit B.
00015  *  
00016  *  Software distributed under the License is distributed on an "AS IS" basis, WITHOUT 
00017  *  WARRANTY OF ANY KIND, either express or implied. See the License for the specific 
00018  *  language governing rights and limitations under the License.
00019  *  
00020  *  The Original Code is LASS - Library of Assembled Shared Sources.
00021  *  
00022  *  The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
00023  *  The Original Developer is the Initial Developer.
00024  *  
00025  *  All portions of the code written by the Initial Developer are:
00026  *  Copyright (C) 2004-2007 the Initial Developer.
00027  *  All Rights Reserved.
00028  *  
00029  *  Contributor(s):
00030  *
00031  *  Alternatively, the contents of this file may be used under the terms of the 
00032  *  GNU General Public License Version 2 or later (the GPL), in which case the 
00033  *  provisions of GPL are applicable instead of those above.  If you wish to allow use
00034  *  of your version of this file only under the terms of the GPL and not to allow 
00035  *  others to use your version of this file under the CPAL, indicate your decision by 
00036  *  deleting the provisions above and replace them with the notice and other 
00037  *  provisions required by the GPL License. If you do not delete the provisions above,
00038  *  a recipient may use your version of this file under either the CPAL or the GPL.
00039  *  
00040  *  *** END LICENSE INFORMATION ***
00041  */
00042 
00043 #include "../meta/is_integral.h"
00044 
00045 namespace lass
00046 {
00047 namespace stde
00048 {
00049 
00050 namespace impl
00051 {
00052 
00053 /** @internal
00054  */
00055 struct slist_traits
00056 {
00057     template <typename Container, typename T>
00058     static void push(Container& container, const T& value)
00059     {
00060         container.push_front(value);
00061     }
00062     template <typename Container>
00063     static void temp_to_output(Container& temp, Container& output)
00064     {
00065         temp.swap(output);
00066     }
00067 };
00068 
00069 }
00070 
00071 
00072 
00073 // --- public --------------------------------------------------------------------------------------
00074 
00075 /** Creates an empty list, using the provided allocator
00076  *
00077  *  @param allocator to be used as memory model, defaults to @c Alloc().
00078  *
00079  *  @b complexity: O(1)
00080  */
00081 template <typename T, class Alloc>
00082 slist<T, Alloc>::slist(const Alloc& allocator):
00083     Alloc(allocator)
00084 {
00085     head_.next = 0;
00086 }
00087 
00088 
00089 
00090 /** Creates an list with @a n elements - each of which is a copy of @a value - and an allocator.
00091  *
00092  *  @param n is the number of copies of @a value to put in the list.
00093  *  @param value will be used to copy construct all of the @a n elements of the list,
00094  *      defaults to @c T().
00095  *  @param allocator to be used as memory model, defaults to @c Alloc().
00096  *
00097  *  @b complexity: O(N) with N = @a n.
00098  */
00099 template <typename T, class Alloc>
00100 slist<T, Alloc>::slist(size_type n, const T& value, const Alloc& allocator):
00101     Alloc(allocator)
00102 {
00103     head_.next = 0;
00104     insert_after(before_begin(), n, value);
00105 }
00106 
00107 
00108 
00109 /** creates a list with as elements a copy of a range, and an allocator.
00110  *
00111  *  @param first iterator to first element of range to be copied in list.
00112  *  @param last iterator to position after the last element to be copied in list.
00113  *      @a last must be forward reachable from @a first.
00114  *  @param allocator to be used as memory model, defaults to @c Alloc().
00115  *
00116  *  @b complexity: O(N) with N = <tt>std::distance(first, last)</tt>.
00117  */
00118 template <typename T, class Alloc>
00119 template <typename InputIterator>
00120 slist<T, Alloc>::slist(InputIterator first, InputIterator last, const Alloc& allocator):
00121     Alloc(allocator)
00122 {
00123     head_.next = 0;
00124     insert_after(before_begin(), first, last);
00125 }
00126 
00127 
00128 
00129 /** copies an entire list and its elements and allocator.
00130  *
00131  *  @param other the list to be copied
00132  *
00133  *  @b complexity: O(N) with N = @c other.size()
00134  */
00135 template <typename T, class Alloc>
00136 slist<T, Alloc>::slist(const slist<T, Alloc>& other):
00137     Alloc(other.get_allocator())
00138 {
00139     head_.next = 0;
00140     insert_after(before_begin(), other.begin(), other.end());
00141 }
00142 
00143 
00144 
00145 /** destroys all elements and frees memory.
00146  *
00147  *  @b complexity: O(N) with N = @c this->size()
00148  */
00149 template <typename T, class Alloc>
00150 slist<T, Alloc>::~slist()
00151 {
00152     while (head_.next)
00153     {
00154         unlink_and_destroy_after(&head_);
00155     }
00156 }
00157 
00158 
00159 
00160 /** replace @c *this by a copy of @a other.
00161  *
00162  *  @param other list to be copied
00163  *
00164  *  @b complexity: O(N1) + O(N2) with N1 = @c this->size() and N2 = @c other.size().
00165  */
00166 template <typename T, class Alloc>
00167 slist<T, Alloc>& slist<T, Alloc>::operator=(slist<T, Alloc> other)
00168 {
00169     swap(other);
00170     return *this;
00171 }
00172 
00173 
00174 
00175 /** replace @c *this by a list copied from a range.
00176  *
00177  *  @param first iterator to first element of range to be copied in list.
00178  *  @param last iterator to position after the last element to be copied in list.
00179  *      @a last must be forward reachable from @a first.
00180  *
00181  *  @b complexity: O(N1) + O(N2) with N1 = @c this->size() and
00182  *      N2 = <tt>std::distance(first, last)</tt>.
00183  */
00184 template <typename T, class Alloc>
00185 template <typename ForwardIterator>
00186 void slist<T, Alloc>::assign(ForwardIterator first, ForwardIterator last)
00187 {
00188     slist<T, Alloc> temp(first, last, get_allocator());
00189     swap(temp);
00190 }
00191 
00192 
00193 
00194 /** replace @c *this by a list with @a n copies of @a value
00195  *
00196  *  @param n is the number of copies of @a value to put in the list.
00197  *  @param value will be used to copy construct all of the @a n elements of the list.
00198  *
00199  *  @b complexity: O(N1) + O(N2) with N1 = @c this->size() and N2 = @a n.
00200  */
00201 template <typename T, class Alloc>
00202 void slist<T, Alloc>::assign(size_type n, const T& value)
00203 {
00204     slist<T, Alloc> temp(n, value, get_allocator());
00205     swap(temp);
00206 }
00207 
00208 
00209 
00210 /** returns the memory model of the list.
00211  *
00212  *  @b complexity: O(1)
00213  */
00214 template <typename T, class Alloc>
00215 typename slist<T, Alloc>::allocator_type
00216 slist<T, Alloc>::get_allocator() const
00217 {
00218     return *static_cast<const allocator_type*>(this);
00219 }
00220 
00221 
00222 
00223 /** returns an iterator to the first element of the list.
00224  *
00225  *  @b complexity: O(1)
00226  */
00227 template <typename T, class Alloc>
00228 typename slist<T, Alloc>::iterator
00229 slist<T, Alloc>::begin()
00230 {
00231     return iterator(head_.next);
00232 }
00233 
00234 
00235 
00236 /** returns an iterator to the first element of the list.
00237  *
00238  *  @b complexity: O(1)
00239  */
00240 template <typename T, class Alloc>
00241 typename slist<T, Alloc>::const_iterator
00242 slist<T, Alloc>::begin() const
00243 {
00244     return const_iterator(head_.next);
00245 }
00246 
00247 
00248 
00249 /** returns an iterator for the position after the last element of the list.
00250  *
00251  *  @b complexity: O(1)
00252  */
00253 template <typename T, class Alloc>
00254 typename slist<T, Alloc>::iterator
00255 slist<T, Alloc>::end()
00256 {
00257     return iterator(0);
00258 }
00259 
00260 
00261 
00262 /** returns an iterator for the position after the last element of the list.
00263  *
00264  *  @b complexity: O(1)
00265  */
00266 template <typename T, class Alloc>
00267 typename slist<T, Alloc>::const_iterator
00268 slist<T, Alloc>::end() const
00269 {
00270     return const_iterator(0);
00271 }
00272 
00273 
00274 
00275 /** returns an iterator for the position before the first element of the list.
00276  *  This iterator is not dereferencable!  It's only an iterator for which the next one is
00277  *  @c this->begin().  Use this one in methods like @c insert_after and @c erase_after when you want
00278  *  the method to affect on the first element in the list.  Using @c begin() would fail for this
00279  *  purpose the element after @c this->begin() is already the second in the list.
00280  *
00281  *  @b complexity: O(1)
00282  */
00283 template <typename T, class Alloc>
00284 typename slist<T, Alloc>::iterator
00285 slist<T, Alloc>::before_begin()
00286 {
00287     return iterator(&head_);
00288 }
00289 
00290 
00291 
00292 /** returns an iterator for the position before the first element of the list.
00293  *  This iterator is not dereferencable!  It's only an iterator for which the next one is
00294  *  @c this->begin().  Use this one in methods like @c insert_after and @c erase_after when you want
00295  *  the method to affect on the first element in the list.  Using @c begin() would fail for this
00296  *  purpose the element after @c this->begin() is already the second in the list.
00297  *
00298  *  @b complexity: O(1)
00299  */
00300 template <typename T, class Alloc>
00301 typename slist<T, Alloc>::const_iterator
00302 slist<T, Alloc>::before_begin() const
00303 {
00304     return const_iterator(&head_);
00305 }
00306 
00307 
00308 
00309 /** return the iterator that sits @a position and start searching for it from @a start.
00310  *  Equivalent to <tt>this->prior(position, this->before_begin())</tt>.
00311  *
00312  *  @param position must be valid in @c *this and should not be @c this->before_begin()
00313  *
00314  *  @b complexity: O(N) with N = <tt>std::distance(this->begin(), position)</tt>
00315  */
00316 template <typename T, class Alloc>
00317 typename slist<T, Alloc>::iterator
00318 slist<T, Alloc>::prior(iterator position) const
00319 {
00320     return prior(position, const_cast<slist<T, Alloc>*>(this)->before_begin());
00321 }
00322 
00323 
00324 
00325 /** return the iterator that sits @a position and start searching for it from @a start.
00326  *  Equivalent to <tt>this->prior(position, this->before_begin())</tt>.
00327  *
00328  *  @param position must be valid in @c *this and should not be @c this->before_begin()
00329  *
00330  *  @b complexity: O(N) with N = <tt>std::distance(this->begin(), position)</tt>
00331  */
00332 template <typename T, class Alloc>
00333 typename slist<T, Alloc>::const_iterator
00334 slist<T, Alloc>::prior(const_iterator position) const
00335 {
00336     return prior(position, before_begin());
00337 }
00338 
00339 
00340 
00341 /** return the iterator that sits @a position and start searching for it from @a start.
00342  *  The method scans linearly all iterators from @a start until it find the one for which the next
00343  *  one is @a position.  It returns the same result as @c std::prior(position) would have returned
00344  *  if the iterator had support for the decrement operation.
00345  *
00346  *  @param position must be valid in @c *this and should not be @c this->before_begin()
00347  *  @param start must be a valid iterator in @c [this->begin(),position)
00348  *
00349  *  @b complexity: O(N) with N = <tt>std::distance(start, position)</tt>
00350  */
00351 template <typename T, class Alloc>
00352 typename slist<T, Alloc>::iterator
00353 slist<T, Alloc>::prior(iterator position, iterator start) const
00354 {
00355     iterator result = start;
00356     while (result.node_->next != position.node_)
00357     {
00358         LASS_ASSERT(result.node_->next);
00359         ++result;
00360     }
00361     return result;
00362 }
00363 
00364 
00365 
00366 /** return the iterator that sits @a position and start searching for it from @a start.
00367  *  The method scans linearly all iterators from @a start until it find the one for which the next
00368  *  one is @a position.  It returns the same result as @c std::prior(position) would have returned
00369  *  if the iterator had support for the decrement operation.
00370  *
00371  *  @param position must be valid in @c *this and should not be @c this->before_begin()
00372  *  @param start must be a valid iterator in @c [this->begin(),position)
00373  *
00374  *  @b complexity: O(N) with N = <tt>std::distance(start, position)</tt>
00375  */
00376 template <typename T, class Alloc>
00377 typename slist<T, Alloc>::const_iterator
00378 slist<T, Alloc>::prior(const_iterator position, const_iterator start) const
00379 {
00380     const_iterator result = start;
00381     while (result.node_->next != position.node_)
00382     {
00383         LASS_ASSERT(result.node_->next);
00384         ++result;
00385     }
00386     return result;
00387 }
00388 
00389 
00390 
00391 /** returns wether the list is empty.
00392  *  Is semantically identical to <tt>this->size() == 0</tt>, but it is a lot faster.
00393  *  So use it whenever you can ... even to do the dishes.
00394  *
00395  *  @b complexity: O(1)
00396  */
00397 template <typename T, class Alloc>
00398 bool slist<T, Alloc>::empty() const
00399 {
00400     return head_.next == 0;
00401 }
00402 
00403 
00404 
00405 /** returns the N, the number of elements in the list.
00406  *
00407  *  @b complexity: O(N) with N = @c this->size().
00408  */
00409 template <typename T, class Alloc>
00410 typename slist<T, Alloc>::size_type
00411 slist<T, Alloc>::size() const
00412 {
00413     size_type n = 0;
00414     for (node_base_t* i = head_.next; i != 0; i = i->next)
00415     {
00416         ++n;
00417     }
00418     return n;
00419 }
00420 
00421 
00422 
00423 /** returns a @e very rough estimation on what's the maximum number of elements you can
00424  *  ever have in an @c slist.
00425  *
00426  *  Frankly, we don't know this number, so we return the highest number we know of =)
00427  *
00428  *  @b complexity: O(1)
00429  */
00430 template <typename T, class Alloc>
00431 typename slist<T, Alloc>::size_type
00432 slist<T, Alloc>::max_size() const
00433 {
00434     // if anyone knows something better, please feel free to do so [Bramz]
00435     //
00436     return size_type(-1);
00437 }
00438 
00439 
00440 
00441 /** at the end of the list, inserts copies of @a value or erases elements so that list size is @a n.
00442  *
00443  *  @param n the size of the list after inserting or erasing elements.
00444  *  @param value if the list must grow, copies of @a value are inserted at the end.
00445  *      Defaults to T().
00446  *
00447  *  @b complexity: O(N) with N = @a n.
00448  */
00449 template <typename T, class Alloc>
00450 void slist<T, Alloc>::resize(size_type n, const T& value)
00451 {
00452     node_base_t* i = &head_;
00453     while (i->next && n)
00454     {
00455         --n;
00456         i = i->next;
00457     }
00458     if (n)
00459     {
00460         insert_after(iterator(i), n, value);
00461     }
00462     else
00463     {
00464         while (i->next)
00465         {
00466             unlink_and_destroy_after(i);
00467         }
00468     }
00469 }
00470 
00471 
00472 
00473 /** returns reference to first element in list.
00474  *
00475  *  @c *this must not be empty.  There's no check on wheter the first element exists.
00476  *  It's semantically equivalent to @c *this->begin()
00477  *
00478  *  @b complexity: O(1)
00479  */
00480 template <typename T, class Alloc>
00481 typename slist<T, Alloc>::reference
00482 slist<T, Alloc>::front()
00483 {
00484     return static_cast<node_t*>(head_.next)->value;
00485 }
00486 
00487 
00488 
00489 /** returns reference to first element in list.
00490  *
00491  *  @c *this must not be empty.  There's no check on wheter the first element exists.
00492  *  It's semantically equivalent to @c *this->begin()
00493  *
00494  *  @b complexity: O(1)
00495  */
00496 template <typename T, class Alloc>
00497 typename slist<T, Alloc>::const_reference
00498 slist<T, Alloc>::front() const
00499 {
00500     return static_cast<node_t*>(head_.next)->value;
00501 }
00502 
00503 
00504 
00505 /** insert a copy of @a value at the front of the list so that the current list comes behind it.
00506  *
00507  *  @param value to be inserted at front
00508  *
00509  *  It's semantically equivalent to <tt>this->insert(this->begin(), value)</tt>.
00510  *  All iterators stay valid.
00511  *
00512  *  @b complexity: O(1)
00513  */
00514 template <typename T, class Alloc>
00515 void slist<T, Alloc>::push_front(const T& value)
00516 {
00517     node_base_t* node = make_node(value);
00518     node->next = head_.next;
00519     head_.next = node;
00520 }
00521 
00522 
00523 
00524 /** erases the first element in the list.
00525  *
00526  *  It's semantically equivalent to <tt>this->erase(this->begin())</tt>.
00527  *  All iterators except @c this->begin() stay valid.
00528  *
00529  *  @b complexity: O(1)
00530  */
00531 template <typename T, class Alloc>
00532 void slist<T, Alloc>::pop_front()
00533 {
00534     unlink_and_destroy_after(&head_);
00535 }
00536 
00537 
00538 
00539 /** inserts a new element before iterator @a position and returns iterator to it.
00540  *
00541  *  @param position must be valid in @c *this and should not be @c this->before_begin()
00542  *  @param value to be inserted
00543  *
00544  *  @warning this operation is in linear time because it has to call @c prior(position).
00545  *  Try to use @c insert_after whenever you can.
00546  *
00547  *  All iterators stay valid.
00548  *
00549  *  @b complexity: O(N) with N = <tt>std::distance(this->begin(), position)</tt>
00550  */
00551 template <typename T, class Alloc>
00552 typename slist<T, Alloc>::iterator
00553 slist<T, Alloc>::insert(iterator position, const T& value)
00554 {
00555     const iterator before_position = prior(position);
00556     return insert_after(before_position, value);
00557 }
00558 
00559 
00560 
00561 /** inserts @a n copies of @a value before iterator @a position.
00562  *
00563  *  @param position must be valid in @c *this and should not be @c this->before_begin()
00564  *  @param n number of copies to be inserted.
00565  *  @param value to be inserted
00566  *
00567  *  @warning this operation is in linear time because it has to call @c prior(position).
00568  *  Try to use @c insert_after whenever you can.
00569  *
00570  *  All iterators stay valid.
00571  *
00572  *  @b complexity: O(N1) + O(N2) with N1 = <tt>std::distance(this->begin(), position)</tt>
00573  *      and N2 = @a n.
00574  */
00575 template <typename T, class Alloc>
00576 void slist<T, Alloc>::insert(iterator position, size_type n, const T& value)
00577 {
00578     const iterator before_position = prior(position);
00579     insert_after(before_position, n, value);
00580 }
00581 
00582 
00583 
00584 /** inserts a copy of a range before iterator @a position.
00585  *
00586  *  @param position must be valid in @c *this and should not be @c this->before_begin()
00587  *  @param first iterator to first element to be inserted.
00588  *  @param last iterator to position after last element to be insert.  Must be forward reachable
00589  *      from @a first.
00590  *
00591  *  @warning this operation is in linear time because it has to call @c prior(position).
00592  *  Try to use @c insert_after whenever you can.
00593  *
00594  *  All iterators stay valid.
00595  *
00596  *  @b complexity: O(N1) + O(N2) with N1 = <tt>std::distance(this->begin(), position)</tt>
00597  *      and N2 = @a <tt>std::distance(first, last)</tt>
00598  */
00599 template <typename T, class Alloc>
00600 template <typename InputIterator>
00601 void slist<T, Alloc>::insert(iterator position, InputIterator first, InputIterator last)
00602 {
00603     const iterator before_position = prior(position);
00604     insert_after(before_position, first, last);
00605 }
00606 
00607 
00608 
00609 /** inserts a new element after iterator @a position and returns iterator to it.
00610  *
00611  *  @param position must be valid in @c *this and should not be @c this->end()
00612  *  @param value to be inserted
00613  *
00614  *  All iterators stay valid.
00615  *
00616  *  @b complexity: O(1)
00617  */
00618 template <typename T, class Alloc>
00619 typename slist<T, Alloc>::iterator
00620 slist<T, Alloc>::insert_after(iterator position, const T& value)
00621 {
00622     node_base_t* new_node = make_node(value);
00623     link_after(position.node_, new_node);
00624     return iterator(new_node);
00625 }
00626 
00627 
00628 
00629 /** inserts @a n copies of @a value after iterator @a position.
00630  *
00631  *  @param position must be valid in @c *this and should not be @c this->end()
00632  *  @param n number of copies to be inserted.
00633  *  @param value to be inserted
00634  *
00635  *  All iterators stay valid.
00636  *
00637  *  @b complexity: O(N) with N = @a n.
00638  */
00639 template <typename T, class Alloc>
00640 void slist<T, Alloc>::insert_after(iterator position, size_type n, const T& value)
00641 {
00642     node_base_t* node = position.node_;
00643     for (size_type i = 0; i < n; ++i)
00644     {
00645         node_t* new_node = make_node(value);
00646         link_after(node, new_node);
00647         node = new_node;
00648     }
00649 }
00650 
00651 
00652 
00653 /** inserts a copy of a range before iterator @a position.
00654  *
00655  *  @param position must be valid in @c *this and should not be @c this->end()
00656  *  @param first iterator to first element to be inserted.
00657  *  @param last iterator to position after last element to be insert.  Must be forward reachable
00658  *      from @a first.
00659  *
00660  *  All iterators stay valid.
00661  *
00662  *  @b complexity: O(N) with N = <tt>std::distance(first, last)</tt>.
00663  */
00664 template <typename T, class Alloc>
00665 template <typename InputIterator>
00666 void slist<T, Alloc>::insert_after(iterator position, InputIterator first, InputIterator last)
00667 {
00668     insert_after(position, first, last, meta::Wrap<typename meta::IsIntegral<InputIterator>::Type>());
00669 }
00670 
00671 
00672 
00673 /** removes element at iterator @a position from the list and return iterator to the next element.
00674  *
00675  *  @param position element to be erased.
00676  *      Must be valid in @c *this and should not be @c this->before_begin() or @c this->end().
00677  *
00678  *  @warning this operation is in linear time because it has to call @c prior(position).
00679  *  Try to use @c erase_after whenever you can.
00680  *
00681  *  All iterators except @a position stay valid.
00682  *
00683  *  @b complexity: O(N) with N = <tt>std::distance(this->begin(), position)</tt>
00684  */
00685 template <typename T, class Alloc>
00686 typename slist<T, Alloc>::iterator
00687 slist<T, Alloc>::erase(iterator position)
00688 {
00689     iterator before_position = prior(position);
00690     erase_after(before_position);
00691     return ++before_position;
00692 }
00693 
00694 
00695 
00696 /** removes element in range from the list and return iterator to the next element.
00697  *
00698  *  @param position iterator to first element to be erased.
00699  *      Must be valid in @c *this and should not be @c this->before_begin() or @c this->end().
00700  *  @param last iterator to position behind last element to be erased, must be valid in
00701  *      @c *this and forward reachable from @a position.
00702  *
00703  *  @warning this operation is in linear time because it has to call @c prior(position).
00704  *  Try to use @c erase_after whenever you can.
00705  *
00706  *  All iterators except these in range [ @a position, @a last ) stay valid.
00707  *
00708  *  @b complexity: O(N1) + O(N2) with N1 = <tt>std::distance(this->begin(), position)</tt> and
00709  *      N2 = <tt>std::distance(position, last)</tt>
00710  */
00711 template <typename T, class Alloc>
00712 typename slist<T, Alloc>::iterator
00713 slist<T, Alloc>::erase(iterator position, iterator last)
00714 {
00715     iterator before_position = prior(position);
00716     erase_after(before_position, last);
00717     return ++before_position;
00718 }
00719 
00720 
00721 
00722 /** removes element after iterator @a position from the list.
00723  *
00724  *  @param position iterator to position before element to be erased, must be valid in @c *this,
00725  *      and should not be @c this->end()
00726  *
00727  *  All iterators except the one after @a position stay valid.
00728  *
00729  *  @b complexity: O(1)
00730  */
00731 template <typename T, class Alloc>
00732 void slist<T, Alloc>::erase_after(iterator position)
00733 {
00734     LASS_ASSERT(position.node_ && position.node_->next);
00735     unlink_and_destroy_after(position.node_);
00736 }
00737 
00738 
00739 
00740 /** removes element in range from the list and return iterator to the next element.
00741  *
00742  *  @param position iterator to position before first element to be erased.
00743  *      Must be valid in @c *this and should not be @c this->end()
00744  *  @param last iterator to position behind last element to be erased, must be valid in
00745  *      @c *this and forward reachable from @a position.
00746  *
00747  *  All iterators except these in range ( @a position, @a last ) stay valid.
00748  *
00749  *  @b complexity: O(N) with N = <tt>std::distance(position, last)</tt>
00750  */
00751 template <typename T, class Alloc>
00752 void slist<T, Alloc>::erase_after(iterator position, iterator last)
00753 {
00754     LASS_ASSERT(position.node_);
00755     while (position.node_->next != last.node_)
00756     {
00757         erase_after(position);
00758     }
00759 }
00760 
00761 
00762 
00763 /** exchange all data between two lists.
00764  *
00765  *  All iterators stay valid.
00766  *
00767  *  @b complexity: O(1)
00768  */
00769 template <typename T, class Alloc>
00770 void slist<T, Alloc>::swap(slist<T, Alloc>& other)
00771 {
00772     LASS_ASSERT(get_allocator() == other.get_allocator());
00773     std::swap(head_.next, other.head_.next);
00774 }
00775 
00776 
00777 
00778 /** removes all elements from the list
00779  *
00780  *  @b complexity: O(N) with N = @c this->size()
00781  */
00782 template <typename T, class Alloc>
00783 void slist<T, Alloc>::clear()
00784 {
00785     slist<T, Alloc> temp(get_allocator());
00786     swap(temp);
00787 }
00788 
00789 
00790 
00791 /** moves all elements from @a other to @c *this before @a position without copying, and
00792  *  clears @a other.
00793  *
00794  *  @param position must be valid in @c *this and should not be @c this->before_begin()
00795  *  @param other must not be the same as @c *this (<tt>&other != this</tt>).
00796  *
00797  *  @warning this operation is in linear time because it has to call @c prior(position).
00798  *  Try to use @c splice_after whenever you can.
00799  *
00800  *  All iterators stay valid.
00801  *
00802  *  @b complexity: O(N1) + O(N2) with N1 = <tt>std::distance(this->begin(), position)</tt>
00803  *      and N2 = @c other.size()
00804  */
00805 template <typename T, class Alloc>
00806 void slist<T, Alloc>::splice(iterator position, slist<T, Alloc>& other)
00807 {
00808     const iterator before_position = prior(position);
00809     splice_after(before_position, other);
00810 }
00811 
00812 
00813 
00814 /** moves @a x from @a other to @c *this before @a position without copying.
00815  *
00816  *  @param position must be valid in @c *this and should not be @c this->before_begin()
00817  *  @param other may be the same as @c *this.
00818  *  @param x must be valid in @c other and should not be @c other.before_begin()
00819  *
00820  *  @warning this operation is in linear time because it has to call @c prior(position) and
00821  *  @c prior(x).  Try to use @c splice_after whenever you can.
00822  *
00823  *  All iterators stay valid.
00824  *
00825  *  @b complexity: O(N1) + O(N2) with N1 = <tt>std::distance(this->begin(), position)</tt>
00826  *      and N2 = <tt>std::distance(other.begin(), x)</tt>
00827  */
00828 template <typename T, class Alloc>
00829 void slist<T, Alloc>::splice(iterator position, slist<T, Alloc>& other, iterator x)
00830 {
00831     const iterator before_position = prior(position);
00832     const iterator before_x = other.prior(x);
00833     splice_after(before_position, other, before_x);
00834 }
00835 
00836 
00837 
00838 /** moves [ @a first , @a last ) from @a other to @c *this before @a position without copying.
00839  *
00840  *  @param position must be valid in @c *this and should not be @c this->before_begin().
00841  *      @a position should not be an element of [ @a first , @a last ).
00842  *  @param other may be the same as @c *this.
00843  *  @param first must be valid in @c other and should not be @c other.before_begin()
00844  *  @param last must be valid in @c other and should be forward reachable from @a first.
00845  *
00846  *  @warning this operation is in linear time because it has to call @c prior(position) and
00847  *  @c prior(x).  Try to use @c splice_after whenever you can.
00848  *
00849  *  All iterators stay valid.
00850  *
00851  *  @b complexity: O(N1) + O(N2) with N1 = <tt>std::distance(this->begin(), position)</tt>
00852  *      and N2 = <tt>std::distance(other.begin(), x)</tt>
00853  */
00854 template <typename T, class Alloc>
00855 void slist<T, Alloc>::splice(iterator position, slist<T, Alloc>& other, iterator first, iterator last)
00856 {
00857     const iterator before_position = prior(position);
00858     const iterator before_first = other.prior(first);
00859     const iterator before_last = other.prior(last, before_first);
00860     splice_after(before_position, other, before_first, before_last);
00861 }
00862 
00863 
00864 
00865 /** moves all elements from @a other to @c *this after @a position without copying, and
00866  *  clears @a other.
00867  *
00868  *  @param position must be valid in @c *this and should not be @c this->end()
00869  *  @param other must not be the same as @c *this (<tt>&other != this</tt>).
00870  *
00871  *  All iterators stay valid.
00872  *
00873  *  @b complexity: O(N) with N = @c other.size()
00874  */
00875 template <typename T, class Alloc>
00876 void slist<T, Alloc>::splice_after(iterator position, slist<T, Alloc>& other)
00877 {
00878     node_base_t* other_before_last = &other.head_;
00879     while (other_before_last->next)
00880     {
00881         other_before_last = other_before_last->next;
00882     }
00883 
00884     splice_after(position.node_, &other.head_, other_before_last);
00885 }
00886 
00887 
00888 
00889 /** moves element before @a before_x from @a other to @c *this after @a position without copying.
00890  *
00891  *  @param position must be valid in @c *this and should not be @c this->end()
00892  *  @param other may be the same as @c *this.
00893  *  @param before_x must be valid in @c other and should not be @c other.end()
00894  *
00895  *  All iterators stay valid.
00896  *
00897  *  @b complexity: O(1)</tt>
00898  */
00899 template <typename T, class Alloc>
00900 void slist<T, Alloc>::splice_after(iterator position, slist<T, Alloc>& /*other*/, iterator before_x)
00901 {
00902     splice_after(position.node_, before_x.node_, before_x.node_->next);
00903 }
00904 
00905 
00906 
00907 /** moves ( before_first, before_last ] from @a other to @c *this after @a position without copying.
00908  *
00909  *  @param position must be valid in @c *this and should not be @c this->end().
00910  *      @a position should not be an element of ( before_first, before_last ].
00911  *  @param other may be the same as @c *this.
00912  *  @param before_first must be valid in @c other and should not be @c other.end()
00913  *  @param before_last must be valid in @c other and should be forward reachable from @a before_first.
00914  *
00915  *  All iterators stay valid.
00916  *
00917  *  @b complexity: O(1)
00918  */
00919 template <typename T, class Alloc>
00920 void slist<T, Alloc>::splice_after(iterator position, slist<T, Alloc>& /*other*/, iterator before_first,
00921                                iterator before_last)
00922 {
00923     splice_after(position.node_, before_first.node_, before_last.node_);
00924 }
00925 
00926 
00927 
00928 /** removes all elements with iterarors @c i for which <tt>*i == value</tt>
00929  *
00930  *  @param value value of the elements that must be removed.
00931  *
00932  *  @b complexity: O(N) with N = @c this->size()
00933  */
00934 template <typename T, class Alloc>
00935 void slist<T, Alloc>::remove(const T& value)
00936 {
00937     node_base_t* node = &head_;
00938     while (node->next)
00939     {
00940         if (static_cast<node_t*>(node->next)->value == value)
00941         {
00942             unlink_and_destroy_after(node);
00943         }
00944         else
00945         {
00946             node = node->next;
00947         }
00948     }
00949 }
00950 
00951 
00952 
00953 /** removes all elements with iterarors @c i for which @c predicate(*i) yields @c true.
00954  *
00955  *  @param predicate should returns true for the elements that must be removed.
00956  *
00957  *  @b complexity: O(N) with N = @c this->size()
00958  */
00959 template <typename T, class Alloc>
00960 template <class UnaryPredicate>
00961 void slist<T, Alloc>::remove_if(UnaryPredicate predicate)
00962 {
00963     node_base_t* node = &head_;
00964     while (node->next)
00965     {
00966         if (predicate(static_cast<node_t*>(node->next)->value))
00967         {
00968             unlink_and_destroy_after(node);
00969         }
00970         else
00971         {
00972             node = node->next;
00973         }
00974     }
00975 }
00976 
00977 
00978 
00979 /** removes all but the first element in every consecutive group of equal elements.
00980  *
00981  *  The relative order of elements that are not removed is unchanged, and iterators to elements
00982  *  that are not removed remain valid.
00983  *
00984  *  @b complexity: O(N) with N = @c this->size()
00985  */
00986 template <typename T, class Alloc>
00987 void slist<T, Alloc>::unique()
00988 {
00989     node_base_t* node = head_.next;
00990     if (!node)
00991     {
00992         return;
00993     }
00994     while (node->next)
00995     {
00996         if (static_cast<node_t*>(node)->value == static_cast<node_t*>(node->next)->value)
00997         {
00998             unlink_and_destroy_after(node);
00999         }
01000         else
01001         {
01002             node = node->next;
01003         }
01004     }
01005 }
01006 
01007 
01008 
01009 /** removes all but the first element in every consecutive group of equivalent elements by a predicate.
01010  *
01011  *  @param predicate two elements @c *i and @c *j are considered equivalent if
01012  *      <tt>predicate(*i, *j)</tt> is true.
01013  *
01014  *  The relative order of elements that are not removed is unchanged, and iterators to elements
01015  *  that are not removed remain valid.
01016  *
01017  *  @b complexity: O(N) with N = @c this->size()
01018  */
01019 template <typename T, class Alloc>
01020 template <class BinaryPredicate>
01021 void slist<T, Alloc>::unique(BinaryPredicate predicate)
01022 {
01023     node_base_t* node = head_.next;
01024     if (!node)
01025     {
01026         return;
01027     }
01028     while (node->next)
01029     {
01030         if (predicate(static_cast<node_t*>(node)->value, static_cast<node_t*>(node->next)->value))
01031         {
01032             unlink_and_destroy_after(node);
01033         }
01034         else
01035         {
01036             node = node->next;
01037         }
01038     }
01039 }
01040 
01041 
01042 
01043 /** Merge two sorted containers to one big sorted.
01044  *
01045  *  Both @c *this and @a other must be sorted according to @c operator<, and they must be
01046  *  distinct (<tt>&other != this</tt>). This function removes all of @a other's elements and
01047  *  inserts them in order into @c *this. The merge is stable; that is, if an element from @c *this
01048  *  is equivalent to one from @a other, then the element from @c *this will precede the one from
01049  *  @a other. All iterators to elements in @c *this and @a other remain valid.
01050  *
01051  *  @param other the other sorted @c slist
01052  *
01053  *  @b complexity: O(N1) + O(N2) with N1 = @c this->size() and N2 = @c other.size()
01054  */
01055 template <typename T, class Alloc>
01056 void slist<T, Alloc>::merge(slist<T, Alloc>& other)
01057 {
01058     merge(other, std::less<value_type>());
01059 }
01060 
01061 
01062 
01063 /** Merge two by @a compare sorted containers to one big sorted.
01064  *
01065  *  Both @c *this and @a other must be sorted according to @a compare, and they must be
01066  *  distinct (<tt>&other != this</tt>). This function removes all of @a other's elements and
01067  *  inserts them in order into @c *this. The merge is stable; that is, if an element from @c *this
01068  *  is equivalent to one from @a other, then the element from @c *this will precede the one from
01069  *  @a other. All iterators to elements in @c *this and @a other remain valid.
01070  *
01071  *  @param other the other sorted @c slist
01072  *  @param compare must define strict weak ordening.  Both containers must be sorted
01073  *      by this predicate.
01074  *
01075  *  @b complexity: O(N1) + O(N2) with N1 = @c this->size() and N2 = @c other.size()
01076  */
01077 template <typename T, class Alloc>
01078 template <class BinaryPredicate>
01079 void slist<T, Alloc>::merge(slist<T, Alloc>& other, BinaryPredicate compare)
01080 {
01081     node_base_t* node = &head_;
01082     while (node->next && other.head_.next)
01083     {
01084         if (compare(static_cast<node_t*>(other.head_.next)->value,
01085                     static_cast<node_t*>(node->next)->value))
01086         {
01087             splice_after(node, &other.head_, other.head_.next);
01088         }
01089         node = node->next;
01090     }
01091     if (other.head_.next)
01092     {
01093         node->next = other.head_.next;
01094         other.head_.next = 0;
01095     }
01096 }
01097 
01098 
01099 
01100 /** Sorts @c *this according to @c operator<.
01101  *
01102  *  The sort is stable, that is, the relative order of equivalent elements is preserved.
01103  *  All iterators remain valid and continue to point to the same elements.
01104  *
01105  *  @b complexity: O(N log N) with N = @c this->size()
01106  */
01107 template <typename T, class Alloc>
01108 void slist<T, Alloc>::sort()
01109 {
01110     sort(std::less<value_type>());
01111 }
01112 
01113 
01114 
01115 
01116 
01117 
01118 
01119 /** Sorts @c *this according to @a compare.
01120  *
01121  *  @param compare must define strict weak ordening.  Both containers must be sorted
01122  *      by this predicate.
01123  *
01124  *  The sort is stable, that is, the relative order of equivalent elements is preserved.
01125  *  All iterators remain valid and continue to point to the same elements.
01126  *
01127  *  @b complexity: O(N log N) with N = @c this->size()
01128  */
01129 template <typename T, class Alloc>
01130 template <class BinaryPredicate>
01131 void slist<T, Alloc>::sort(BinaryPredicate compare)
01132 {
01133     if (head_.next && head_.next->next)
01134     {
01135         slist<T, Alloc> carry;
01136         slist<T, Alloc> counter[64];
01137         size_type fill = 0;
01138         while (!empty())
01139         {
01140             splice_after(&carry.head_, &head_, head_.next);
01141             size_type i = 0;
01142             while (i < fill && !counter[i].empty())
01143             {
01144                 counter[i].merge(carry, compare);
01145                 carry.swap(counter[i]);
01146                 ++i;
01147             }
01148             carry.swap(counter[i]);
01149             if (i == fill)
01150             {
01151                 ++fill;
01152             }
01153         }
01154         for (size_type i = 1; i < fill; ++i)
01155         {
01156             counter[i].merge(counter[i - 1], compare);
01157         }
01158         swap(counter[fill - 1]);
01159     }
01160 }
01161 
01162 
01163 
01164 /** reverses the order of the elements.
01165  *
01166  *  All iterators stay valid.
01167  *
01168  *  @b complexity: O(N) with N = @c this->size()
01169  */
01170 template <typename T, class Alloc>
01171 void slist<T, Alloc>::reverse()
01172 {
01173     node_base_t* begin = 0;
01174     while (head_.next)
01175     {
01176         node_base_t* node = head_.next;
01177         head_.next = node->next;
01178         node->next = begin;
01179         begin = node;
01180     }
01181     head_.next = begin;
01182 }
01183 
01184 // --- protected -----------------------------------------------------------------------------------
01185 
01186 
01187 
01188 // --- private -------------------------------------------------------------------------------------
01189 
01190 /** @internal
01191  */
01192 template <typename T, class Alloc>
01193 typename slist<T, Alloc>::node_t*
01194 slist<T, Alloc>::make_node(const T& value) const
01195 {
01196     allocator_type allocator = get_allocator();
01197     node_allocator_type node_allocator = node_allocator_type(allocator);
01198 
01199     node_t* node = node_allocator.allocate(1);
01200     try
01201     {
01202         allocator.construct(&node->value, value);
01203     }
01204     catch (...)
01205     {
01206         node_allocator.deallocate(node, 1);
01207         throw;
01208     }
01209     node->next = 0;
01210     return node;
01211 }
01212 
01213 
01214 
01215 /** @internal
01216  */
01217 template <typename T, class Alloc>
01218 void slist<T, Alloc>::unlink_and_destroy_after(node_base_t* before) const
01219 {
01220     allocator_type allocator = get_allocator();
01221     node_allocator_type node_allocator = node_allocator_type(allocator);
01222 
01223     LASS_ASSERT(before && before->next);
01224 
01225     node_base_t* node = before->next;
01226     before->next = node->next;
01227     allocator.destroy(&static_cast<node_t*>(node)->value);
01228     node_allocator.deallocate(static_cast<node_t*>(node), 1);
01229 }
01230 
01231 
01232 
01233 /** @internal
01234  */
01235 template <typename T, class Alloc>
01236 void slist<T, Alloc>::link_after(node_base_t* position, node_base_t* node) const
01237 {
01238     LASS_ASSERT(position && node);
01239     node->next = position->next;
01240     position->next = node;
01241 }
01242 
01243 
01244 
01245 /** @internal
01246  */
01247 template <typename T, class Alloc>
01248 void slist<T, Alloc>::splice_after(node_base_t* position, node_base_t* before_first,
01249                                    node_base_t* before_last) const
01250 {
01251     LASS_ASSERT(before_first != before_last);
01252     if (position != before_first && position != before_last)
01253     {
01254         node_base_t* const first = before_first->next;
01255         before_first->next = before_last->next;
01256         before_last->next = position->next;
01257         position->next = first;
01258     }
01259 }
01260 
01261 
01262 
01263 /** @internal
01264  */
01265 template <typename T, class Alloc>
01266 void slist<T, Alloc>::insert_after(iterator position, size_type n, const value_type& value,
01267                                    meta::Wrap<meta::True>)
01268 {
01269     node_base_t* node = position.node_;
01270     for (size_type i = 0; i < n; ++i)
01271     {
01272         node_t* new_node = make_node(value);
01273         link_after(node, new_node);
01274         node = new_node;
01275     }
01276 }
01277 
01278 
01279 
01280 /** @internal
01281  */
01282 template <typename T, class Alloc>
01283 template <typename InputIterator>
01284 void slist<T, Alloc>::insert_after(iterator position, InputIterator first, InputIterator last,
01285                                    meta::Wrap<meta::False>)
01286 {
01287     while (first != last)
01288     {
01289         node_t* new_node = make_node(*first);
01290         link_after(position.node_, new_node);
01291         ++position;
01292         ++first;
01293     }
01294 }
01295 
01296 
01297 
01298 // --- free functions ------------------------------------------------------------------------------
01299 
01300 /** returns wether @a a and @a b are lexicographical idential.
01301  *  @relates slist
01302  *
01303  *  @param a first @c slist
01304  *  @param b second @c slist
01305  *
01306  *  returns true if <tt>a.size() == b.size()</tt> and each element of @a is considered
01307  *  equal to its corresponding element in @a b by using @c operator==
01308  *
01309  *  @complexity O(N) with N = <tt>a.size() == b.size() ? a.size() : 1</tt>
01310  */
01311 template <typename T, class Alloc>
01312 bool operator==(const slist<T, Alloc>& a, const slist<T, Alloc>& b)
01313 {
01314     typedef typename slist<T, Alloc>::const_iterator const_iterator;
01315     const const_iterator a_end = a.end();
01316     const const_iterator b_end = b.end();
01317     const_iterator i = a.begin();
01318     const_iterator j = b.begin();
01319     while (i != a_end && j != b_end)
01320     {
01321         if (*i != *j)
01322         {
01323             return false;
01324         }
01325         ++i;
01326         ++j;
01327     }
01328     return i == a_end && j == b_end;
01329 }
01330 
01331 
01332 
01333 /** returns wether @a a and @a b are not lexicographical idential.
01334  *  @relates slist
01335  *
01336  *  @param a first @c slist
01337  *  @param b second @c slist
01338  *
01339  *  Is equivalent to <tt>!(a == b)</tt>
01340  *
01341  *  @complexity O(N) with N = <tt>a.size() == b.size() ? a.size() : 1</tt>
01342  */
01343 template <typename T, class Alloc>
01344 bool operator!=(const slist<T, Alloc>& a, const slist<T, Alloc>& b)
01345 {
01346     return !(a == b);
01347 }
01348 
01349 
01350 
01351 /** returns wether @a a is lexicographical less than @a b.
01352  *  @relates slist
01353  *
01354  *  @param a first @c slist
01355  *  @param b second @c slist
01356  *
01357  *  returns true if for the first difference between @a a and @a b the element of @a a is less
01358  *  than the corresponding one of @a b.  In case no different elements between @a and @a b can be
01359  *  found, it returns true if <tt>a.size() < b.size()</tt>
01360  *
01361  *  @complexity O(N) with N = <tt>std::min(a.size(), b.size())</tt>
01362  */
01363 template <typename T, class Alloc>
01364 bool operator<(const slist<T, Alloc>& a, const slist<T, Alloc>& b)
01365 {
01366     typedef typename slist<T, Alloc>::const_iterator const_iterator;
01367     const const_iterator a_end = a.end();
01368     const const_iterator b_end = b.end();
01369     const_iterator i = a.begin();
01370     const_iterator j = b.begin();
01371     while (i != a_end && j != b_end)
01372     {
01373         if (!(*i < *j))
01374         {
01375             return false;
01376         }
01377         ++i;
01378         ++j;
01379     }
01380     return j != b_end;
01381 }
01382 
01383 
01384 
01385 /** returns wether @a b is lexicographical less than @a a.
01386  *  @relates slist
01387  *
01388  *  @param a first @c slist
01389  *  @param b second @c slist
01390  *
01391  *  Is equivalent to <tt>(b < a)</tt>
01392  *
01393  *  @complexity O(N) with N = <tt>std::min(a.size(), b.size())</tt>
01394  */
01395 template <typename T, class Alloc>
01396 bool operator>(const slist<T, Alloc>& a, const slist<T, Alloc>& b)
01397 {
01398     return b < a;
01399 }
01400 
01401 
01402 
01403 /** returns wether @a a is lexicographical less or equal to @a b.
01404  *  @relates slist
01405  *
01406  *  @param a first @c slist
01407  *  @param b second @c slist
01408  *
01409  *  Is equivalent to <tt>!(b < a)</tt>
01410  *
01411  *  @complexity O(N) with N = <tt>std::min(a.size(), b.size())</tt>
01412  */
01413 template <typename T, class Alloc>
01414 bool operator<=(const slist<T, Alloc>& a, const slist<T, Alloc>& b)
01415 {
01416     return !(b < a);
01417 }
01418 
01419 
01420 
01421 /** returns wether @a b is lexicographical less or equal to @a a.
01422  *  @relates slist
01423  *
01424  *  @param a first @c slist
01425  *  @param b second @c slist
01426  *
01427  *  Is equivalent to <tt>!(a < b)</tt>
01428  *
01429  *  @complexity O(N) with N = <tt>std::min(a.size(), b.size())</tt>
01430  */
01431 template <typename T, class Alloc>
01432 bool operator>=(const slist<T, Alloc>& a, const slist<T, Alloc>& b)
01433 {
01434     return !(a < b);
01435 }
01436 
01437 
01438 
01439 /** @relates slist
01440  *  writes list to output stream.
01441  *
01442  *  @param ostream should be a good stream.
01443  *  @param container @c slist to be written as [foo, bar, spam, ham]
01444  *
01445  *  @b complexity: O(N) with N = @c container.size()
01446  */
01447 template <typename T, class Alloc, typename Char, typename Traits>
01448 std::basic_ostream<Char, Traits>&
01449 operator<<(std::basic_ostream<Char, Traits>& ostream,
01450            const slist<T, Alloc>& container)
01451 {
01452     return impl::print_sequence(
01453         ostream, container.begin(), container.end(), "[", ", ", "]");
01454 }
01455 
01456 
01457 
01458 /** @relates slist
01459  *  reads list from stream.
01460  *
01461  *  @param istream should be a good stream.
01462  *  @param container @c slist to be read as [foo, bar, spam, ham]
01463  *
01464  *  @b complexity: O(N) with N = number of elements to be read.
01465  */
01466 template <typename T, class Alloc, typename Char, typename Traits>
01467 std::basic_istream<Char, Traits>&
01468 operator>>(std::basic_istream<Char, Traits>& istream,
01469            slist<T, Alloc>& container)
01470 {
01471     std::basic_istream<Char, Traits>& result =
01472         impl::read_container<impl::slist_traits, impl::value_traits, T, Char>(
01473             istream, container, '[', ',', 0, ']');
01474     container.reverse();
01475     return result;
01476 }
01477 
01478 
01479 
01480 }
01481 
01482 }
01483 
01484 // EOF

Generated on Mon Nov 10 14:21:34 2008 for Library of Assembled Shared Sources by doxygen 1.5.7.1
SourceForge.net Logo