// -*- C++ -*- // Copyright (C) 2008 // Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 2, 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 General Public License for more details. // You should have received a copy of the GNU General Public License // along with this library; see the file COPYING. If not, write to // the Free Software Foundation, 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. // As a special exception, you may use this file as part of a free software // library without restriction. Specifically, if other files instantiate // templates or use macros or inline functions from this file, or you compile // this file and link it with other files to produce an executable, this // file does not by itself cause the resulting executable to be covered by // the GNU General Public License. This exception does not however // invalidate any other reasons why the executable file might be covered by // the GNU General Public License. /** @file forward_list.tcc * This is a Standard C++ Library header. */ #ifndef _FORWARD_LIST_TCC #define _FORWARD_LIST_TCC 1 namespace std { /** * @brief Sort the singly linked list starting after this node. * This node is assumed to be an empty head node (of type * _Fwd_list_node_base). */ template template void _Fwd_list_node<_Tp>::_M_sort_after(_Comp __comp) { // If `next' is 0, return immediately. _Fwd_list_node* __list = static_cast<_Fwd_list_node*>(this->_M_next); if (!__list) return; unsigned int __insize = 1; while (1) { _Fwd_list_node* __p = __list; __list = 0; _Fwd_list_node* __tail = 0; // Count number of merges we do in this pass. unsigned int __nmerges = 0; while (__p) { ++__nmerges; // There exists a merge to be done. // Step `insize' places along from p. _Fwd_list_node* __q = __p; unsigned int __psize = 0; for (int __i = 0; __i < __insize; ++__i) { ++__psize; __q = static_cast<_Fwd_list_node*>(__q->_M_next); if (!__q) break; } // If q hasn't fallen off end, we have two lists to merge. unsigned int __qsize = __insize; // Now we have two lists; merge them. while (__psize > 0 || (__qsize > 0 && __q)) { // Decide whether next node of merge comes from p or q. _Fwd_list_node<_Tp>* __e; if (__psize == 0) { // p is empty; e must come from q. __e = __q; __q = static_cast<_Fwd_list_node*>(__q->_M_next); --__qsize; } else if (__qsize == 0 || !__q) { // q is empty; e must come from p. __e = __p; __p = static_cast<_Fwd_list_node*>(__p->_M_next); --__psize; } else if (__comp(__p->_M_value, __q->_M_value)) { // First node of p is lower; e must come from p. __e = __p; __p = static_cast<_Fwd_list_node*>(__p->_M_next); --__psize; } else { // First node of q is lower; e must come from q. __e = __q; __q = static_cast<_Fwd_list_node*>(__q->_M_next); --__qsize; } // Add the next node to the merged list. if (__tail) __tail->_M_next = __e; else __list = __e; __tail = __e; } // Now p has stepped `insize' places along, and q has too. __p = __q; } __tail->_M_next = 0; // If we have done only one merge, we're finished. // Allow for nmerges == 0, the empty list case. if (__nmerges <= 1) { this->_M_next = __list; return; } // Otherwise repeat, merging lists twice the size. __insize *= 2; } } } // namespace std #endif /* _FORWARD_LIST_TCC */