diff options
author | Jason Merrill <jason@gcc.gnu.org> | 1997-08-21 18:57:35 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 1997-08-21 18:57:35 -0400 |
commit | 6599da043e22e96ac830fb50a61c1b6d95d1b142 (patch) | |
tree | a3b19970338bdae580faff126a716e1d5520400c /libstdc++/stl | |
parent | 8975416cfb6269ad94b6330d42960cca8b0925b7 (diff) | |
download | gcc-6599da043e22e96ac830fb50a61c1b6d95d1b142.zip gcc-6599da043e22e96ac830fb50a61c1b6d95d1b142.tar.gz gcc-6599da043e22e96ac830fb50a61c1b6d95d1b142.tar.bz2 |
Initial revision
From-SVN: r14877
Diffstat (limited to 'libstdc++/stl')
30 files changed, 17933 insertions, 0 deletions
diff --git a/libstdc++/stl/ChangeLog b/libstdc++/stl/ChangeLog new file mode 100644 index 0000000..b519b18 --- /dev/null +++ b/libstdc++/stl/ChangeLog @@ -0,0 +1,192 @@ +Tue Aug 5 17:06:01 1997 Jason Merrill <jason@yorick.cygnus.com> + + * deque.h, function.h, hashtable.h, list.h, rope.h, ropeimpl.h, + tree.h: Update to July 31 SGI release. + +Fri Jul 18 10:06:56 1997 Jason Merrill <jason@yorick.cygnus.com> + + * algo.h, defalloc.h, hashtable.h, rope.h, ropeimpl.h, slist.h: + Update to June 30 SGI release. + +Fri Jul 04 02:17:15 1997 Ulrich Drepper <drepper@cygnus.com> + + * tree.h (rb_tree): Reverse order of member initializations + to prevent warnings. + +Sun Jun 15 18:17:21 1997 Jason Merrill <jason@yorick.cygnus.com> + + * *.h: Update to 6/13 SGI release. + +Fri May 23 10:56:18 1997 Jason Merrill <jason@yorick.cygnus.com> + + * stl_config.h: Add support for exceptions with g++. + + * *.h: Update to 5/8 SGI release. + +Thu Apr 24 19:00:23 1997 Jason Merrill <jason@yorick.cygnus.com> + + * *.h: Update to 3/24 SGI release. + +Wed Feb 19 18:19:18 1997 Jason Merrill <jason@yorick.cygnus.com> + + * *.h: Update to 2/18 SGI release. + + * bool.h: Lose. + +Mon Feb 10 16:33:23 1997 Jason Merrill <jason@yorick.cygnus.com> + + * alloc.h: Don't define __USE_MALLOC for g++. + * bool.h: Lose g++ case. + + * *.h: Update to 2/4 SGI release. + +Mon Jan 13 14:39:16 1997 Jason Merrill <jason@yorick.cygnus.com> + + * *.h: Update to 1/8 SGI release. + +Mon Sep 30 17:56:43 1996 Jason Merrill <jason@yorick.cygnus.com> + + * alloc.h (__unlock): Never use __lock_release. + +Fri Sep 27 19:03:06 1996 Jason Merrill <jason@yorick.cygnus.com> + + * alloc.h (__default_alloc_template): lock is a friend. + +Thu Sep 19 20:10:37 1996 Jason Merrill <jason@yorick.cygnus.com> + + Propagate these changes to new STL code: + * tree.h: Rearrange member initializers in rb_tree constructors. + * vector.h (insert): Cast iterator difference to size_type to + avoid warning. + + * *.h: Update to SGI snapshot (fixed). + * *.c, Makefile.in, configure.in: Removed. + +Sat Sep 14 09:43:06 1996 Jason Merrill <jason@yorick.cygnus.com> + + * deque.h, list.h, tree.h: Remove kludge obsoleted by new + overloading code. + +Sat Aug 10 14:59:50 1996 Jason Merrill <jason@yorick.cygnus.com> + + * tempbuf.cc (__stl_temp_buffer): Align like a pointer. + +Wed Jun 26 13:00:44 1996 Jason Merrill <jason@yorick.cygnus.com> + + * iterator.h: Add default template parameters. + +Wed Apr 24 10:45:22 1996 Doug Evans <dje@blues.cygnus.com> + + * Makefile.in (tempbuf.o,random.o): Add rules for SunOS VPATH. + +Fri Apr 5 17:52:31 1996 Per Bothner <bothner@kalessin.cygnus.com> + + * configure.in (EXTRA_MOSTLYCLEAN): New, to remove stl.list. + +Fri Mar 22 14:58:30 1996 Jason Merrill <jason@yorick.cygnus.com> + + Propagate these changes to new STL code: + * tree.h: Rearrange member initializers in rb_tree constructors. + * vector.h (insert): Cast iterator difference to size_type to + avoid warning. + +Sun Mar 10 07:49:03 1996 Jason Merrill <jason@yorick.cygnus.com> + + * deque.h (distance_type): Add overload for g++. + From Joe Buck. + +Thu Feb 22 14:07:12 1996 Jason Merrill <jason@yorick.cygnus.com> + + * bool.h: Revert. + * algo.h bvector.h deque.h function.h iterator.h list.h + pair.h stack.h tree.h vector.h: Wrap #include <bool.h> with + #ifndef __GNUG__. + * defalloc.h list.h deque.h tree.h: Use __GNUG__ to control + workarounds. + +Wed Feb 21 17:13:02 1996 Jason Merrill <jason@yorick.cygnus.com> + + * bool.h (TRUE, FALSE): Define for people expecting the bool.h + from libg++. Is this a good idea? + +Tue Feb 20 18:40:02 1996 Jason Merrill <jason@yorick.cygnus.com> + + * algo.h bool.h bvector.h defalloc.h deque.h function.h heap.h + iterator.h list.h map.h pair.h random.cc stack.h tree.c tree.h + vector.h: Revert to HP release with workarounds for missing + overloading functionality. + * Makefile.in (STL_OBJECTS): Remove tree.o. + +Thu Nov 9 17:05:23 1995 Jason Merrill <jason@yorick.cygnus.com> + + * algo.h algobase.h bvector.h defalloc.h deque.h function.h heap.h + iterator.h list.h map.h multimap.h multiset.h pair.h projectn.h + set.h stack.h tempbuf.h tree.h vector.h: Wrap #include <bool.h> + with #ifndef __GNUG__. + +Thu Nov 2 17:05:44 1995 Jason Merrill <jason@yorick.cygnus.com> + + * deque.h (deque<T>::insert): Fix merge typo. + * vector.h (value_type): Lose. + +Thu Nov 2 14:33:47 1995 Per Bothner <bothner@kalessin.cygnus.com> + + * algo.h, algobase.h, deque.h, function.h, list.h, pair.h, random.cc: + Merge in Oct 31 1995 release from HP. + +Fri Aug 11 17:11:12 1995 Per Bothner <bothner@kalessin.cygnus.com> + + * list.h: Avoid duplicate construction and destruction of list_nodes. + Patch from Klamer Schutte <klamer@ph.tn.tudelft.nl>. + +Fri Aug 11 16:45:18 1995 Per Bothner <bothner@kalessin.cygnus.com> + + * algo.h, algobase.h, deque.h: Merged in Jul 12 1995 release from HP. + +Mon Jun 5 18:38:56 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * Makefile.in (stl.list): Depend on stamp-picdir. + +Wed May 17 02:30:47 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * tree.h: Rearrange member initializers in rb_tree constructors. + + * Update to HP's February 7, 1995 release. + +Fri May 5 10:45:31 1995 Mike Stump <mrs@cygnus.com> + + * random.cc (seed): Move `for' decl out of `for' statement. + +Wed Apr 26 13:09:16 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * configure.in (XCXXINCLUDES): Rename. + +Wed Mar 29 19:24:56 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * tree.h (insert): Return a value. + + * vector.h (insert): Cast iterator difference to size_type to + avoid warning. + +Sun Feb 12 09:12:17 1995 Mike Stump <mrs@cygnus.com> + + * tree.h (rb_tree::max_size): Add definition when using GNU + workaround. + +Thu Jan 12 01:37:42 1995 deanm@medulla.LABS.TEK.COM (Dean Messing) + + * configure.in (LIBDIR): Set to yes. + +Fri Dec 30 18:26:20 1994 Mike Stump <mrs@cygnus.com> + + * iterator.h: Add default template parameters where possible. + +Fri Dec 30 16:29:39 1994 Mike Stump <mrs@cygnus.com> + + * algo.h: Change rand to __rand to fix make check on linux systems. + +Tue Nov 29 15:30:30 1994 Per Bothner <bothner@kalessin.cygnus.com> + + * Initial check-in, based on HP's October 21, 1994. + + diff --git a/libstdc++/stl/README b/libstdc++/stl/README new file mode 100644 index 0000000..81bc7cf --- /dev/null +++ b/libstdc++/stl/README @@ -0,0 +1,16 @@ +This directory contains an SGI release of the C++ Standard Template +Library, slightly modified to work with g++ (version 2.8.0 or newer). + +Note that this is based on a pre-Draft Standard for C++. +Things are likely to change. For example, the header file names +are very likely to change. The Allocator interface will change. Etc, etc. +CYGNUS MAKES NO COMMITTMENT (yet) TO SUPPORT BACKWARD COMPATIBILITY FOR STL. + +For examples if things that should work, look in the ../tests directory. + +DOCUMENTATION: +See http://www.sgi.com/Technology/STL/ or http://www.dinkumware.com/ +on the World-Wide Web. + + --Jason Merrill +Cygnus Support jason@cygnus.com diff --git a/libstdc++/stl/algo.h b/libstdc++/stl/algo.h new file mode 100644 index 0000000..69f43c1 --- /dev/null +++ b/libstdc++/stl/algo.h @@ -0,0 +1,2665 @@ +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#ifndef __SGI_STL_ALGO_H +#define __SGI_STL_ALGO_H + +#include <stdlib.h> +#include <limits.h> +#include <algobase.h> +#include <heap.h> +#include <tempbuf.h> + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma set woff 1209 +#endif + +template <class T> +inline const T& __median(const T& a, const T& b, const T& c) { + if (a < b) + if (b < c) + return b; + else if (a < c) + return c; + else + return a; + else if (a < c) + return a; + else if (b < c) + return c; + else + return b; +} + +template <class T, class Compare> +inline const T& __median(const T& a, const T& b, const T& c, Compare comp) { + if (comp(a, b)) + if (comp(b, c)) + return b; + else if (comp(a, c)) + return c; + else + return a; + else if (comp(a, c)) + return a; + else if (comp(b, c)) + return c; + else + return b; +} + +template <class InputIterator, class Function> +Function for_each(InputIterator first, InputIterator last, Function f) { + for ( ; first != last; ++first) + f(*first); + return f; +} + +template <class InputIterator, class T> +InputIterator find(InputIterator first, InputIterator last, const T& value) { + while (first != last && *first != value) ++first; + return first; +} + +template <class InputIterator, class Predicate> +InputIterator find_if(InputIterator first, InputIterator last, + Predicate pred) { + while (first != last && !pred(*first)) ++first; + return first; +} + +template <class ForwardIterator> +ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last) { + if (first == last) return last; + ForwardIterator next = first; + while(++next != last) { + if (*first == *next) return first; + first = next; + } + return last; +} + +template <class ForwardIterator, class BinaryPredicate> +ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last, + BinaryPredicate binary_pred) { + if (first == last) return last; + ForwardIterator next = first; + while(++next != last) { + if (binary_pred(*first, *next)) return first; + first = next; + } + return last; +} + +template <class InputIterator, class T, class Size> +void count(InputIterator first, InputIterator last, const T& value, + Size& n) { + for ( ; first != last; ++first) + if (*first == value) + ++n; +} + +template <class InputIterator, class Predicate, class Size> +void count_if(InputIterator first, InputIterator last, Predicate pred, + Size& n) { + for ( ; first != last; ++first) + if (pred(*first)) + ++n; +} + +#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION + +template <class InputIterator, class T> +iterator_traits<InputIterator>::difference_type +count(InputIterator first, InputIterator last, const T& value) { + iterator_traits<InputIterator>::difference_type n = 0; + for ( ; first != last; ++first) + if (*first == value) + ++n; + return n; +} + +template <class InputIterator, class Predicate> +iterator_traits<InputIterator>::difference_type +count_if(InputIterator first, InputIterator last, Predicate pred) { + iterator_traits<InputIterator>::difference_type n = 0; + for ( ; first != last; ++first) + if (pred(*first)) + ++n; + return n; +} + + +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +template <class ForwardIterator1, class ForwardIterator2, class Distance1, + class Distance2> +ForwardIterator1 __search(ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + Distance1*, Distance2*) { + Distance1 d1 = 0; + distance(first1, last1, d1); + Distance2 d2 = 0; + distance(first2, last2, d2); + + if (d1 < d2) return last1; + + ForwardIterator1 current1 = first1; + ForwardIterator2 current2 = first2; + + while (current2 != last2) + if (*current1 == *current2) { + ++current1; + ++current2; + } + else { + if (d1 == d2) + return last1; + else { + current1 = ++first1; + current2 = first2; + --d1; + } + } + return first1; +} + +template <class ForwardIterator1, class ForwardIterator2> +inline ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2) +{ + return __search(first1, last1, first2, last2, distance_type(first1), + distance_type(first2)); +} + +template <class ForwardIterator1, class ForwardIterator2, + class BinaryPredicate, class Distance1, class Distance2> +ForwardIterator1 __search(ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + BinaryPredicate binary_pred, Distance1*, Distance2*) { + Distance1 d1 = 0; + distance(first1, last1, d1); + Distance2 d2 = 0; + distance(first2, last2, d2); + + if (d1 < d2) return last1; + + ForwardIterator1 current1 = first1; + ForwardIterator2 current2 = first2; + + while (current2 != last2) + if (binary_pred(*current1, *current2)) { + ++current1; + ++current2; + } + else { + if (d1 == d2) + return last1; + else { + current1 = ++first1; + current2 = first2; + --d1; + } + } + return first1; +} + +template <class ForwardIterator1, class ForwardIterator2, + class BinaryPredicate> +inline ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + BinaryPredicate binary_pred) { + return __search(first1, last1, first2, last2, binary_pred, + distance_type(first1), distance_type(first2)); +} + +template <class ForwardIterator1, class ForwardIterator2> +ForwardIterator2 swap_ranges(ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2) { + for ( ; first1 != last1; ++first1, ++first2) + iter_swap(first1, first2); + return first2; +} + +template <class InputIterator, class OutputIterator, class UnaryOperation> +OutputIterator transform(InputIterator first, InputIterator last, + OutputIterator result, UnaryOperation op) { + for ( ; first != last; ++first, ++result) + *result = op(*first); + return result; +} + +template <class InputIterator1, class InputIterator2, class OutputIterator, + class BinaryOperation> +OutputIterator transform(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, OutputIterator result, + BinaryOperation binary_op) { + for ( ; first1 != last1; ++first1, ++first2, ++result) + *result = binary_op(*first1, *first2); + return result; +} + +template <class ForwardIterator, class T> +void replace(ForwardIterator first, ForwardIterator last, const T& old_value, + const T& new_value) { + for ( ; first != last; ++first) + if (*first == old_value) *first = new_value; +} + +template <class ForwardIterator, class Predicate, class T> +void replace_if(ForwardIterator first, ForwardIterator last, Predicate pred, + const T& new_value) { + for ( ; first != last; ++first) + if (pred(*first)) *first = new_value; +} + +template <class InputIterator, class OutputIterator, class T> +OutputIterator replace_copy(InputIterator first, InputIterator last, + OutputIterator result, const T& old_value, + const T& new_value) { + for ( ; first != last; ++first, ++result) + *result = *first == old_value ? new_value : *first; + return result; +} + +template <class Iterator, class OutputIterator, class Predicate, class T> +OutputIterator replace_copy_if(Iterator first, Iterator last, + OutputIterator result, Predicate pred, + const T& new_value) { + for ( ; first != last; ++first, ++result) + *result = pred(*first) ? new_value : *first; + return result; +} + +template <class ForwardIterator, class Generator> +void generate(ForwardIterator first, ForwardIterator last, Generator gen) { + for ( ; first != last; ++first) + *first = gen(); +} + +template <class OutputIterator, class Size, class Generator> +OutputIterator generate_n(OutputIterator first, Size n, Generator gen) { + for ( ; n > 0; --n, ++first) + *first = gen(); + return first; +} + +template <class InputIterator, class OutputIterator, class T> +OutputIterator remove_copy(InputIterator first, InputIterator last, + OutputIterator result, const T& value) { + for ( ; first != last; ++first) + if (*first != value) { + *result = *first; + ++result; + } + return result; +} + +template <class InputIterator, class OutputIterator, class Predicate> +OutputIterator remove_copy_if(InputIterator first, InputIterator last, + OutputIterator result, Predicate pred) { + for ( ; first != last; ++first) + if (!pred(*first)) { + *result = *first; + ++result; + } + return result; +} + +template <class ForwardIterator, class T> +ForwardIterator remove(ForwardIterator first, ForwardIterator last, + const T& value) { + first = find(first, last, value); + ForwardIterator next = first; + return first == last ? first : remove_copy(++next, last, first, value); +} + +template <class ForwardIterator, class Predicate> +ForwardIterator remove_if(ForwardIterator first, ForwardIterator last, + Predicate pred) { + first = find_if(first, last, pred); + ForwardIterator next = first; + return first == last ? first : remove_copy_if(++next, last, first, pred); +} + +template <class InputIterator, class ForwardIterator> +ForwardIterator __unique_copy(InputIterator first, InputIterator last, + ForwardIterator result, forward_iterator_tag) { + *result = *first; + while (++first != last) + if (*result != *first) *++result = *first; + return ++result; +} + +template <class InputIterator, class BidirectionalIterator> +inline BidirectionalIterator __unique_copy(InputIterator first, + InputIterator last, + BidirectionalIterator result, + bidirectional_iterator_tag) { + return __unique_copy(first, last, result, forward_iterator_tag()); +} + +template <class InputIterator, class RandomAccessIterator> +inline RandomAccessIterator __unique_copy(InputIterator first, + InputIterator last, + RandomAccessIterator result, + random_access_iterator_tag) { + return __unique_copy(first, last, result, forward_iterator_tag()); +} + +template <class InputIterator, class OutputIterator, class T> +OutputIterator __unique_copy(InputIterator first, InputIterator last, + OutputIterator result, T*) { + T value = *first; + *result = value; + while (++first != last) + if (value != *first) { + value = *first; + *++result = value; + } + return ++result; +} + +template <class InputIterator, class OutputIterator> +inline OutputIterator __unique_copy(InputIterator first, InputIterator last, + OutputIterator result, + output_iterator_tag) { + return __unique_copy(first, last, result, value_type(first)); +} + +template <class InputIterator, class OutputIterator> +inline OutputIterator unique_copy(InputIterator first, InputIterator last, + OutputIterator result) { + if (first == last) return result; + return __unique_copy(first, last, result, iterator_category(result)); +} +template <class InputIterator, class ForwardIterator, class BinaryPredicate> +ForwardIterator __unique_copy(InputIterator first, InputIterator last, + ForwardIterator result, + BinaryPredicate binary_pred, + forward_iterator_tag) { + *result = *first; + while (++first != last) + if (!binary_pred(*result, *first)) *++result = *first; + return ++result; +} + +template <class InputIterator, class BidirectionalIterator, + class BinaryPredicate> +inline BidirectionalIterator __unique_copy(InputIterator first, + InputIterator last, + BidirectionalIterator result, + BinaryPredicate binary_pred, + bidirectional_iterator_tag) { + return __unique_copy(first, last, result, binary_pred, + forward_iterator_tag()); +} + +template <class InputIterator, class RandomAccessIterator, + class BinaryPredicate> +inline RandomAccessIterator __unique_copy(InputIterator first, + InputIterator last, + RandomAccessIterator result, + BinaryPredicate binary_pred, + random_access_iterator_tag) { + return __unique_copy(first, last, result, binary_pred, + forward_iterator_tag()); +} + +template <class InputIterator, class OutputIterator, class BinaryPredicate, + class T> +OutputIterator __unique_copy(InputIterator first, InputIterator last, + OutputIterator result, + BinaryPredicate binary_pred, T*) { + T value = *first; + *result = value; + while (++first != last) + if (!binary_pred(value, *first)) { + value = *first; + *++result = value; + } + return ++result; +} + +template <class InputIterator, class OutputIterator, class BinaryPredicate> +inline OutputIterator __unique_copy(InputIterator first, InputIterator last, + OutputIterator result, + BinaryPredicate binary_pred, + output_iterator_tag) { + return __unique_copy(first, last, result, binary_pred, value_type(first)); +} + +template <class InputIterator, class OutputIterator, class BinaryPredicate> +inline OutputIterator unique_copy(InputIterator first, InputIterator last, + OutputIterator result, + BinaryPredicate binary_pred) { + if (first == last) return result; + return __unique_copy(first, last, result, binary_pred, + iterator_category(result)); +} + +template <class ForwardIterator> +ForwardIterator unique(ForwardIterator first, ForwardIterator last) { + first = adjacent_find(first, last); + return unique_copy(first, last, first); +} + +template <class ForwardIterator, class BinaryPredicate> +ForwardIterator unique(ForwardIterator first, ForwardIterator last, + BinaryPredicate binary_pred) { + first = adjacent_find(first, last, binary_pred); + return unique_copy(first, last, first, binary_pred); +} + +template <class BidirectionalIterator> +void __reverse(BidirectionalIterator first, BidirectionalIterator last, + bidirectional_iterator_tag) { + while (true) + if (first == last || first == --last) + return; + else + iter_swap(first++, last); +} + +template <class RandomAccessIterator> +void __reverse(RandomAccessIterator first, RandomAccessIterator last, + random_access_iterator_tag) { + while (first < last) iter_swap(first++, --last); +} + +template <class BidirectionalIterator> +inline void reverse(BidirectionalIterator first, BidirectionalIterator last) { + __reverse(first, last, iterator_category(first)); +} + +template <class BidirectionalIterator, class OutputIterator> +OutputIterator reverse_copy(BidirectionalIterator first, + BidirectionalIterator last, + OutputIterator result) { + while (first != last) { + --last; + *result = *last; + ++result; + } + return result; +} + +template <class ForwardIterator, class Distance> +void __rotate(ForwardIterator first, ForwardIterator middle, + ForwardIterator last, Distance*, forward_iterator_tag) { + for (ForwardIterator i = middle; ;) { + iter_swap(first, i); + ++first; + ++i; + if (first == middle) { + if (i == last) return; + middle = i; + } + else if (i == last) + i = middle; + } +} + +template <class BidirectionalIterator, class Distance> +void __rotate(BidirectionalIterator first, BidirectionalIterator middle, + BidirectionalIterator last, Distance*, + bidirectional_iterator_tag) { + reverse(first, middle); + reverse(middle, last); + reverse(first, last); +} + +template <class EuclideanRingElement> +EuclideanRingElement __gcd(EuclideanRingElement m, EuclideanRingElement n) +{ + while (n != 0) { + EuclideanRingElement t = m % n; + m = n; + n = t; + } + return m; +} + +template <class RandomAccessIterator, class Distance, class T> +void __rotate_cycle(RandomAccessIterator first, RandomAccessIterator last, + RandomAccessIterator initial, Distance shift, T*) { + T value = *initial; + RandomAccessIterator ptr1 = initial; + RandomAccessIterator ptr2 = ptr1 + shift; + while (ptr2 != initial) { + *ptr1 = *ptr2; + ptr1 = ptr2; + if (last - ptr2 > shift) + ptr2 += shift; + else + ptr2 = first + (shift - (last - ptr2)); + } + *ptr1 = value; +} + +template <class RandomAccessIterator, class Distance> +void __rotate(RandomAccessIterator first, RandomAccessIterator middle, + RandomAccessIterator last, Distance*, + random_access_iterator_tag) { + Distance n = __gcd(last - first, middle - first); + while (n--) + __rotate_cycle(first, last, first + n, middle - first, + value_type(first)); +} + +template <class ForwardIterator> +inline void rotate(ForwardIterator first, ForwardIterator middle, + ForwardIterator last) { + if (first == middle || middle == last) return; + __rotate(first, middle, last, distance_type(first), + iterator_category(first)); +} + +template <class ForwardIterator, class OutputIterator> +OutputIterator rotate_copy(ForwardIterator first, ForwardIterator middle, + ForwardIterator last, OutputIterator result) { + return copy(first, middle, copy(middle, last, result)); +} + +template <class RandomAccessIterator, class Distance> +void __random_shuffle(RandomAccessIterator first, RandomAccessIterator last, + Distance*) { + if (first == last) return; + for (RandomAccessIterator i = first + 1; i != last; ++i) +#ifdef __STL_NO_DRAND48 + iter_swap(i, first + Distance(rand() % ((i - first) + 1))); +#else + iter_swap(i, first + Distance(lrand48() % ((i - first) + 1))); +#endif +} + +template <class RandomAccessIterator> +inline void random_shuffle(RandomAccessIterator first, + RandomAccessIterator last) { + __random_shuffle(first, last, distance_type(first)); +} + +template <class RandomAccessIterator, class RandomNumberGenerator> +void random_shuffle(RandomAccessIterator first, RandomAccessIterator last, + RandomNumberGenerator& rand) { + if (first == last) return; + for (RandomAccessIterator i = first + 1; i != last; ++i) + iter_swap(i, first + rand((i - first) + 1)); +} + +template <class ForwardIterator, class OutputIterator, class Distance> +OutputIterator random_sample_n(ForwardIterator first, ForwardIterator last, + OutputIterator out, const Distance n) +{ + Distance remaining = 0; + distance(first, last, remaining); + Distance m = min(n, remaining); + + while (m > 0) { +#ifdef __STL_NO_DRAND48 + if (rand() % remaining < m) { +#else + if (lrand48() % remaining < m) { +#endif + *out = *first; + ++out; + --m; + } + + --remaining; + ++first; + } + return out; +} + +template <class ForwardIterator, class OutputIterator, class Distance, + class RandomNumberGenerator> +OutputIterator random_sample_n(ForwardIterator first, ForwardIterator last, + OutputIterator out, const Distance n, + RandomNumberGenerator& rand) +{ + Distance remaining = 0; + distance(first, last, remaining); + Distance m = min(n, remaining); + + while (m > 0) { + if (rand(remaining) < m) { + *out = *first; + ++out; + --m; + } + + --remaining; + ++first; + } + return out; +} + +template <class InputIterator, class RandomAccessIterator, class Distance> +RandomAccessIterator __random_sample(InputIterator first, InputIterator last, + RandomAccessIterator out, + const Distance n) +{ + Distance m = 0; + Distance t = n; + for ( ; first != last && m < n; ++m, ++first) + out[m] = *first; + + while (first != last) { + ++t; +#ifdef __STL_NO_DRAND48 + Distance M = rand() % t; +#else + Distance M = lrand48() % t; +#endif + if (M < n) + out[M] = *first; + ++first; + } + + return out + m; +} + +template <class InputIterator, class RandomAccessIterator, + class RandomNumberGenerator, class Distance> +RandomAccessIterator __random_sample(InputIterator first, InputIterator last, + RandomAccessIterator out, + RandomNumberGenerator& rand, + const Distance n) +{ + Distance m = 0; + Distance t = n; + for ( ; first != last && m < n; ++m, ++first) + out[m] = *first; + + while (first != last) { + ++t; + Distance M = rand(t); + if (M < n) + out[M] = *first; + ++first; + } + + return out + m; +} + +template <class InputIterator, class RandomAccessIterator> +inline RandomAccessIterator +random_sample(InputIterator first, InputIterator last, + RandomAccessIterator out_first, RandomAccessIterator out_last) +{ + return __random_sample(first, last, out_first, out_last - out_first); +} + +template <class InputIterator, class RandomAccessIterator, + class RandomNumberGenerator> +inline RandomAccessIterator +random_sample(InputIterator first, InputIterator last, + RandomAccessIterator out_first, RandomAccessIterator out_last, + RandomNumberGenerator& rand) +{ + return __random_sample(first, last, out_first, rand, out_last - out_first); +} + + + +template <class BidirectionalIterator, class Predicate> +BidirectionalIterator partition(BidirectionalIterator first, + BidirectionalIterator last, Predicate pred) { + while (true) { + while (true) + if (first == last) + return first; + else if (pred(*first)) + ++first; + else + break; + --last; + while (true) + if (first == last) + return first; + else if (!pred(*last)) + --last; + else + break; + iter_swap(first, last); + ++first; + } +} + +template <class ForwardIterator, class Predicate, class Distance> +ForwardIterator __inplace_stable_partition(ForwardIterator first, + ForwardIterator last, + Predicate pred, Distance len) { + if (len == 1) return pred(*first) ? last : first; + ForwardIterator middle = first; + advance(middle, len / 2); + ForwardIterator + first_cut = __inplace_stable_partition(first, middle, pred, len / 2); + ForwardIterator + second_cut = __inplace_stable_partition(middle, last, pred, + len - len / 2); + rotate(first_cut, middle, second_cut); + len = 0; + distance(middle, second_cut, len); + advance(first_cut, len); + return first_cut; +} + +template <class ForwardIterator, class Pointer, class Predicate, + class Distance> +ForwardIterator __stable_partition_adaptive(ForwardIterator first, + ForwardIterator last, + Predicate pred, Distance len, + Pointer buffer, + Distance buffer_size) { + if (len <= buffer_size) { + ForwardIterator result1 = first; + Pointer result2 = buffer; + for ( ; first != last ; ++first) + if (pred(*first)) { + *result1 = *first; + ++result1; + } + else { + *result2 = *first; + ++result2; + } + copy(buffer, result2, result1); + return result1; + } + else { + ForwardIterator middle = first; + advance(middle, len / 2); + ForwardIterator first_cut = + __stable_partition_adaptive(first, middle, pred, len / 2, + buffer, buffer_size); + ForwardIterator second_cut = + __stable_partition_adaptive(middle, last, pred, len - len / 2, + buffer, buffer_size); + + rotate(first_cut, middle, second_cut); + len = 0; + distance(middle, second_cut, len); + advance(first_cut, len); + return first_cut; + } +} + +template <class ForwardIterator, class Predicate, class T, class Distance> +inline ForwardIterator __stable_partition_aux(ForwardIterator first, + ForwardIterator last, + Predicate pred, T*, Distance*) { + temporary_buffer<ForwardIterator, T> buf(first, last); + if (buf.size() > 0) + return __stable_partition_adaptive(first, last, pred, + Distance(buf.requested_size()), + buf.begin(), buf.size()); + else + return __inplace_stable_partition(first, last, pred, + Distance(buf.requested_size())); +} + +template <class ForwardIterator, class Predicate> +inline ForwardIterator stable_partition(ForwardIterator first, + ForwardIterator last, + Predicate pred) { + if (first == last) + return first; + else + return __stable_partition_aux(first, last, pred, + value_type(first), distance_type(first)); +} + +template <class RandomAccessIterator, class T> +RandomAccessIterator __unguarded_partition(RandomAccessIterator first, + RandomAccessIterator last, + T pivot) { + while (1) { + while (*first < pivot) ++first; + --last; + while (pivot < *last) --last; + if (!(first < last)) return first; + iter_swap(first, last); + ++first; + } +} + +template <class RandomAccessIterator, class T, class Compare> +RandomAccessIterator __unguarded_partition(RandomAccessIterator first, + RandomAccessIterator last, + T pivot, Compare comp) { + while (1) { + while (comp(*first, pivot)) ++first; + --last; + while (comp(pivot, *last)) --last; + if (!(first < last)) return first; + iter_swap(first, last); + ++first; + } +} + +const int __stl_threshold = 16; + + +template <class RandomAccessIterator, class T> +void __unguarded_linear_insert(RandomAccessIterator last, T value) { + RandomAccessIterator next = last; + --next; + while (value < *next) { + *last = *next; + last = next; + --next; + } + *last = value; +} + +template <class RandomAccessIterator, class T, class Compare> +void __unguarded_linear_insert(RandomAccessIterator last, T value, + Compare comp) { + RandomAccessIterator next = last; + --next; + while (comp(value , *next)) { + *last = *next; + last = next; + --next; + } + *last = value; +} + +template <class RandomAccessIterator, class T> +inline void __linear_insert(RandomAccessIterator first, + RandomAccessIterator last, T*) { + T value = *last; + if (value < *first) { + copy_backward(first, last, last + 1); + *first = value; + } else + __unguarded_linear_insert(last, value); +} + +template <class RandomAccessIterator, class T, class Compare> +inline void __linear_insert(RandomAccessIterator first, + RandomAccessIterator last, T*, Compare comp) { + T value = *last; + if (comp(value, *first)) { + copy_backward(first, last, last + 1); + *first = value; + } else + __unguarded_linear_insert(last, value, comp); +} + +template <class RandomAccessIterator> +void __insertion_sort(RandomAccessIterator first, RandomAccessIterator last) { + if (first == last) return; + for (RandomAccessIterator i = first + 1; i != last; ++i) + __linear_insert(first, i, value_type(first)); +} + +template <class RandomAccessIterator, class Compare> +void __insertion_sort(RandomAccessIterator first, + RandomAccessIterator last, Compare comp) { + if (first == last) return; + for (RandomAccessIterator i = first + 1; i != last; ++i) + __linear_insert(first, i, value_type(first), comp); +} + +template <class RandomAccessIterator, class T> +void __unguarded_insertion_sort_aux(RandomAccessIterator first, + RandomAccessIterator last, T*) { + for (RandomAccessIterator i = first; i != last; ++i) + __unguarded_linear_insert(i, T(*i)); +} + +template <class RandomAccessIterator> +inline void __unguarded_insertion_sort(RandomAccessIterator first, + RandomAccessIterator last) { + __unguarded_insertion_sort_aux(first, last, value_type(first)); +} + +template <class RandomAccessIterator, class T, class Compare> +void __unguarded_insertion_sort_aux(RandomAccessIterator first, + RandomAccessIterator last, + T*, Compare comp) { + for (RandomAccessIterator i = first; i != last; ++i) + __unguarded_linear_insert(i, T(*i), comp); +} + +template <class RandomAccessIterator, class Compare> +inline void __unguarded_insertion_sort(RandomAccessIterator first, + RandomAccessIterator last, + Compare comp) { + __unguarded_insertion_sort_aux(first, last, value_type(first), comp); +} + +template <class RandomAccessIterator> +void __final_insertion_sort(RandomAccessIterator first, + RandomAccessIterator last) { + if (last - first > __stl_threshold) { + __insertion_sort(first, first + __stl_threshold); + __unguarded_insertion_sort(first + __stl_threshold, last); + } else + __insertion_sort(first, last); +} + +template <class RandomAccessIterator, class Compare> +void __final_insertion_sort(RandomAccessIterator first, + RandomAccessIterator last, Compare comp) { + if (last - first > __stl_threshold) { + __insertion_sort(first, first + __stl_threshold, comp); + __unguarded_insertion_sort(first + __stl_threshold, last, comp); + } else + __insertion_sort(first, last, comp); +} + +template <class Size> +Size __lg(Size n) { + Size k; + for (k = 0; n != 1; n = n / 2) ++k; + return k; +} + +template <class RandomAccessIterator, class T, class Size> +void __introsort_loop(RandomAccessIterator first, + RandomAccessIterator last, T*, + Size depth_limit) { + while (last - first > __stl_threshold) { + if (depth_limit == 0) { + partial_sort(first, last, last); + return; + } + --depth_limit; + RandomAccessIterator cut = __unguarded_partition + (first, last, T(__median(*first, *(first + (last - first)/2), + *(last - 1)))); + __introsort_loop(cut, last, value_type(first), depth_limit); + last = cut; + } +} + +template <class RandomAccessIterator, class T, class Size, class Compare> +void __introsort_loop(RandomAccessIterator first, + RandomAccessIterator last, T*, + Size depth_limit, Compare comp) { + while (last - first > __stl_threshold) { + if (depth_limit == 0) { + partial_sort(first, last, last, comp); + return; + } + --depth_limit; + RandomAccessIterator cut = __unguarded_partition + (first, last, T(__median(*first, *(first + (last - first)/2), + *(last - 1), comp)), comp); + __introsort_loop(cut, last, value_type(first), depth_limit, comp); + last = cut; + } +} + +template <class RandomAccessIterator> +inline void sort(RandomAccessIterator first, RandomAccessIterator last) { + if (first != last) { + __introsort_loop(first, last, value_type(first), __lg(last - first) * 2); + __final_insertion_sort(first, last); + } +} + +template <class RandomAccessIterator, class Compare> +inline void sort(RandomAccessIterator first, RandomAccessIterator last, + Compare comp) { + if (first != last) { + __introsort_loop(first, last, value_type(first), __lg(last - first) * 2, + comp); + __final_insertion_sort(first, last, comp); + } +} + + +template <class RandomAccessIterator> +void __inplace_stable_sort(RandomAccessIterator first, + RandomAccessIterator last) { + if (last - first < 15) { + __insertion_sort(first, last); + return; + } + RandomAccessIterator middle = first + (last - first) / 2; + __inplace_stable_sort(first, middle); + __inplace_stable_sort(middle, last); + __merge_without_buffer(first, middle, last, middle - first, last - middle); +} + +template <class RandomAccessIterator, class Compare> +void __inplace_stable_sort(RandomAccessIterator first, + RandomAccessIterator last, Compare comp) { + if (last - first < 15) { + __insertion_sort(first, last, comp); + return; + } + RandomAccessIterator middle = first + (last - first) / 2; + __inplace_stable_sort(first, middle, comp); + __inplace_stable_sort(middle, last, comp); + __merge_without_buffer(first, middle, last, middle - first, + last - middle, comp); +} + +template <class RandomAccessIterator1, class RandomAccessIterator2, + class Distance> +void __merge_sort_loop(RandomAccessIterator1 first, + RandomAccessIterator1 last, + RandomAccessIterator2 result, Distance step_size) { + Distance two_step = 2 * step_size; + + while (last - first >= two_step) { + result = merge(first, first + step_size, + first + step_size, first + two_step, result); + first += two_step; + } + + step_size = min(Distance(last - first), step_size); + merge(first, first + step_size, first + step_size, last, result); +} + +template <class RandomAccessIterator1, class RandomAccessIterator2, + class Distance, class Compare> +void __merge_sort_loop(RandomAccessIterator1 first, + RandomAccessIterator1 last, + RandomAccessIterator2 result, Distance step_size, + Compare comp) { + Distance two_step = 2 * step_size; + + while (last - first >= two_step) { + result = merge(first, first + step_size, + first + step_size, first + two_step, result, comp); + first += two_step; + } + step_size = min(Distance(last - first), step_size); + + merge(first, first + step_size, first + step_size, last, result, comp); +} + +const int __stl_chunk_size = 7; + +template <class RandomAccessIterator, class Distance> +void __chunk_insertion_sort(RandomAccessIterator first, + RandomAccessIterator last, Distance chunk_size) { + while (last - first >= chunk_size) { + __insertion_sort(first, first + chunk_size); + first += chunk_size; + } + __insertion_sort(first, last); +} + +template <class RandomAccessIterator, class Distance, class Compare> +void __chunk_insertion_sort(RandomAccessIterator first, + RandomAccessIterator last, + Distance chunk_size, Compare comp) { + while (last - first >= chunk_size) { + __insertion_sort(first, first + chunk_size, comp); + first += chunk_size; + } + __insertion_sort(first, last, comp); +} + +template <class RandomAccessIterator, class Pointer, class Distance> +void __merge_sort_with_buffer(RandomAccessIterator first, + RandomAccessIterator last, + Pointer buffer, Distance*) { + Distance len = last - first; + Pointer buffer_last = buffer + len; + + Distance step_size = __stl_chunk_size; + __chunk_insertion_sort(first, last, step_size); + + while (step_size < len) { + __merge_sort_loop(first, last, buffer, step_size); + step_size *= 2; + __merge_sort_loop(buffer, buffer_last, first, step_size); + step_size *= 2; + } +} + +template <class RandomAccessIterator, class Pointer, class Distance, + class Compare> +void __merge_sort_with_buffer(RandomAccessIterator first, + RandomAccessIterator last, Pointer buffer, + Distance*, Compare comp) { + Distance len = last - first; + Pointer buffer_last = buffer + len; + + Distance step_size = __stl_chunk_size; + __chunk_insertion_sort(first, last, step_size, comp); + + while (step_size < len) { + __merge_sort_loop(first, last, buffer, step_size, comp); + step_size *= 2; + __merge_sort_loop(buffer, buffer_last, first, step_size, comp); + step_size *= 2; + } +} + +template <class RandomAccessIterator, class Pointer, class Distance> +void __stable_sort_adaptive(RandomAccessIterator first, + RandomAccessIterator last, Pointer buffer, + Distance buffer_size) { + Distance len = (last - first + 1) / 2; + RandomAccessIterator middle = first + len; + if (len > buffer_size) { + __stable_sort_adaptive(first, middle, buffer, buffer_size); + __stable_sort_adaptive(middle, last, buffer, buffer_size); + } else { + __merge_sort_with_buffer(first, middle, buffer, (Distance*)0); + __merge_sort_with_buffer(middle, last, buffer, (Distance*)0); + } + __merge_adaptive(first, middle, last, Distance(middle - first), + Distance(last - middle), buffer, buffer_size); +} + +template <class RandomAccessIterator, class Pointer, class Distance, + class Compare> +void __stable_sort_adaptive(RandomAccessIterator first, + RandomAccessIterator last, Pointer buffer, + Distance buffer_size, Compare comp) { + Distance len = (last - first + 1) / 2; + RandomAccessIterator middle = first + len; + if (len > buffer_size) { + __stable_sort_adaptive(first, middle, buffer, buffer_size, + comp); + __stable_sort_adaptive(middle, last, buffer, buffer_size, + comp); + } else { + __merge_sort_with_buffer(first, middle, buffer, (Distance*)0, comp); + __merge_sort_with_buffer(middle, last, buffer, (Distance*)0, comp); + } + __merge_adaptive(first, middle, last, Distance(middle - first), + Distance(last - middle), buffer, buffer_size, + comp); +} + +template <class RandomAccessIterator, class T, class Distance> +inline void __stable_sort_aux(RandomAccessIterator first, + RandomAccessIterator last, T*, Distance*) { + temporary_buffer<RandomAccessIterator, T> buf(first, last); + if (buf.begin() == 0) + __inplace_stable_sort(first, last); + else + __stable_sort_adaptive(first, last, buf.begin(), Distance(buf.size())); +} + +template <class RandomAccessIterator, class T, class Distance, class Compare> +inline void __stable_sort_aux(RandomAccessIterator first, + RandomAccessIterator last, T*, Distance*, + Compare comp) { + temporary_buffer<RandomAccessIterator, T> buf(first, last); + if (buf.begin() == 0) + __inplace_stable_sort(first, last, comp); + else + __stable_sort_adaptive(first, last, buf.begin(), Distance(buf.size()), + comp); +} + +template <class RandomAccessIterator> +inline void stable_sort(RandomAccessIterator first, + RandomAccessIterator last) { + __stable_sort_aux(first, last, value_type(first), distance_type(first)); +} + +template <class RandomAccessIterator, class Compare> +inline void stable_sort(RandomAccessIterator first, + RandomAccessIterator last, Compare comp) { + __stable_sort_aux(first, last, value_type(first), distance_type(first), + comp); +} + +template <class RandomAccessIterator, class T> +void __partial_sort(RandomAccessIterator first, RandomAccessIterator middle, + RandomAccessIterator last, T*) { + make_heap(first, middle); + for (RandomAccessIterator i = middle; i < last; ++i) + if (*i < *first) + __pop_heap(first, middle, i, T(*i), distance_type(first)); + sort_heap(first, middle); +} + +template <class RandomAccessIterator> +inline void partial_sort(RandomAccessIterator first, + RandomAccessIterator middle, + RandomAccessIterator last) { + __partial_sort(first, middle, last, value_type(first)); +} + +template <class RandomAccessIterator, class T, class Compare> +void __partial_sort(RandomAccessIterator first, RandomAccessIterator middle, + RandomAccessIterator last, T*, Compare comp) { + make_heap(first, middle, comp); + for (RandomAccessIterator i = middle; i < last; ++i) + if (comp(*i, *first)) + __pop_heap(first, middle, i, T(*i), comp, distance_type(first)); + sort_heap(first, middle, comp); +} + +template <class RandomAccessIterator, class Compare> +inline void partial_sort(RandomAccessIterator first, + RandomAccessIterator middle, + RandomAccessIterator last, Compare comp) { + __partial_sort(first, middle, last, value_type(first), comp); +} + +template <class InputIterator, class RandomAccessIterator, class Distance, + class T> +RandomAccessIterator __partial_sort_copy(InputIterator first, + InputIterator last, + RandomAccessIterator result_first, + RandomAccessIterator result_last, + Distance*, T*) { + if (result_first == result_last) return result_last; + RandomAccessIterator result_real_last = result_first; + while(first != last && result_real_last != result_last) { + *result_real_last = *first; + ++result_real_last; + ++first; + } + make_heap(result_first, result_real_last); + while (first != last) { + if (*first < *result_first) + __adjust_heap(result_first, Distance(0), + Distance(result_real_last - result_first), T(*first)); + ++first; + } + sort_heap(result_first, result_real_last); + return result_real_last; +} + +template <class InputIterator, class RandomAccessIterator> +inline RandomAccessIterator +partial_sort_copy(InputIterator first, InputIterator last, + RandomAccessIterator result_first, + RandomAccessIterator result_last) { + return __partial_sort_copy(first, last, result_first, result_last, + distance_type(result_first), value_type(first)); +} + +template <class InputIterator, class RandomAccessIterator, class Compare, + class Distance, class T> +RandomAccessIterator __partial_sort_copy(InputIterator first, + InputIterator last, + RandomAccessIterator result_first, + RandomAccessIterator result_last, + Compare comp, Distance*, T*) { + if (result_first == result_last) return result_last; + RandomAccessIterator result_real_last = result_first; + while(first != last && result_real_last != result_last) { + *result_real_last = *first; + ++result_real_last; + ++first; + } + make_heap(result_first, result_real_last, comp); + while (first != last) { + if (comp(*first, *result_first)) + __adjust_heap(result_first, Distance(0), + Distance(result_real_last - result_first), T(*first), + comp); + ++first; + } + sort_heap(result_first, result_real_last, comp); + return result_real_last; +} + +template <class InputIterator, class RandomAccessIterator, class Compare> +inline RandomAccessIterator +partial_sort_copy(InputIterator first, InputIterator last, + RandomAccessIterator result_first, + RandomAccessIterator result_last, Compare comp) { + return __partial_sort_copy(first, last, result_first, result_last, comp, + distance_type(result_first), value_type(first)); +} + +template <class RandomAccessIterator, class T> +void __nth_element(RandomAccessIterator first, RandomAccessIterator nth, + RandomAccessIterator last, T*) { + while (last - first > 3) { + RandomAccessIterator cut = __unguarded_partition + (first, last, T(__median(*first, *(first + (last - first)/2), + *(last - 1)))); + if (cut <= nth) + first = cut; + else + last = cut; + } + __insertion_sort(first, last); +} + +template <class RandomAccessIterator> +inline void nth_element(RandomAccessIterator first, RandomAccessIterator nth, + RandomAccessIterator last) { + __nth_element(first, nth, last, value_type(first)); +} + +template <class RandomAccessIterator, class T, class Compare> +void __nth_element(RandomAccessIterator first, RandomAccessIterator nth, + RandomAccessIterator last, T*, Compare comp) { + while (last - first > 3) { + RandomAccessIterator cut = __unguarded_partition + (first, last, T(__median(*first, *(first + (last - first)/2), + *(last - 1), comp)), comp); + if (cut <= nth) + first = cut; + else + last = cut; + } + __insertion_sort(first, last, comp); +} + +template <class RandomAccessIterator, class Compare> +inline void nth_element(RandomAccessIterator first, RandomAccessIterator nth, + RandomAccessIterator last, Compare comp) { + __nth_element(first, nth, last, value_type(first), comp); +} + +template <class ForwardIterator, class T, class Distance> +ForwardIterator __lower_bound(ForwardIterator first, ForwardIterator last, + const T& value, Distance*, + forward_iterator_tag) { + Distance len = 0; + distance(first, last, len); + Distance half; + ForwardIterator middle; + + while (len > 0) { + half = len / 2; + middle = first; + advance(middle, half); + if (*middle < value) { + first = middle; + ++first; + len = len - half - 1; + } else + len = half; + } + return first; +} + +template <class ForwardIterator, class T, class Distance> +inline ForwardIterator __lower_bound(ForwardIterator first, + ForwardIterator last, + const T& value, Distance*, + bidirectional_iterator_tag) { + return __lower_bound(first, last, value, (Distance*)0, + forward_iterator_tag()); +} + +template <class RandomAccessIterator, class T, class Distance> +RandomAccessIterator __lower_bound(RandomAccessIterator first, + RandomAccessIterator last, const T& value, + Distance*, random_access_iterator_tag) { + Distance len = last - first; + Distance half; + RandomAccessIterator middle; + + while (len > 0) { + half = len / 2; + middle = first + half; + if (*middle < value) { + first = middle + 1; + len = len - half - 1; + } else + len = half; + } + return first; +} + +template <class ForwardIterator, class T> +inline ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, + const T& value) { + return __lower_bound(first, last, value, distance_type(first), + iterator_category(first)); +} + +template <class ForwardIterator, class T, class Compare, class Distance> +ForwardIterator __lower_bound(ForwardIterator first, ForwardIterator last, + const T& value, Compare comp, Distance*, + forward_iterator_tag) { + Distance len = 0; + distance(first, last, len); + Distance half; + ForwardIterator middle; + + while (len > 0) { + half = len / 2; + middle = first; + advance(middle, half); + if (comp(*middle, value)) { + first = middle; + ++first; + len = len - half - 1; + } else + len = half; + } + return first; +} + +template <class ForwardIterator, class T, class Compare, class Distance> +inline ForwardIterator __lower_bound(ForwardIterator first, + ForwardIterator last, + const T& value, Compare comp, Distance*, + bidirectional_iterator_tag) { + return __lower_bound(first, last, value, comp, (Distance*)0, + forward_iterator_tag()); +} + +template <class RandomAccessIterator, class T, class Compare, class Distance> +RandomAccessIterator __lower_bound(RandomAccessIterator first, + RandomAccessIterator last, + const T& value, Compare comp, Distance*, + random_access_iterator_tag) { + Distance len = last - first; + Distance half; + RandomAccessIterator middle; + + while (len > 0) { + half = len / 2; + middle = first + half; + if (comp(*middle, value)) { + first = middle + 1; + len = len - half - 1; + } else + len = half; + } + return first; +} + +template <class ForwardIterator, class T, class Compare> +inline ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, + const T& value, Compare comp) { + return __lower_bound(first, last, value, comp, distance_type(first), + iterator_category(first)); +} + +template <class ForwardIterator, class T, class Distance> +ForwardIterator __upper_bound(ForwardIterator first, ForwardIterator last, + const T& value, Distance*, + forward_iterator_tag) { + Distance len = 0; + distance(first, last, len); + Distance half; + ForwardIterator middle; + + while (len > 0) { + half = len / 2; + middle = first; + advance(middle, half); + if (value < *middle) + len = half; + else { + first = middle; + ++first; + len = len - half - 1; + } + } + return first; +} + +template <class ForwardIterator, class T, class Distance> +inline ForwardIterator __upper_bound(ForwardIterator first, + ForwardIterator last, + const T& value, Distance*, + bidirectional_iterator_tag) { + return __upper_bound(first, last, value, (Distance*)0, + forward_iterator_tag()); +} + +template <class RandomAccessIterator, class T, class Distance> +RandomAccessIterator __upper_bound(RandomAccessIterator first, + RandomAccessIterator last, const T& value, + Distance*, random_access_iterator_tag) { + Distance len = last - first; + Distance half; + RandomAccessIterator middle; + + while (len > 0) { + half = len / 2; + middle = first + half; + if (value < *middle) + len = half; + else { + first = middle + 1; + len = len - half - 1; + } + } + return first; +} + +template <class ForwardIterator, class T> +inline ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, + const T& value) { + return __upper_bound(first, last, value, distance_type(first), + iterator_category(first)); +} + +template <class ForwardIterator, class T, class Compare, class Distance> +ForwardIterator __upper_bound(ForwardIterator first, ForwardIterator last, + const T& value, Compare comp, Distance*, + forward_iterator_tag) { + Distance len = 0; + distance(first, last, len); + Distance half; + ForwardIterator middle; + + while (len > 0) { + half = len / 2; + middle = first; + advance(middle, half); + if (comp(value, *middle)) + len = half; + else { + first = middle; + ++first; + len = len - half - 1; + } + } + return first; +} + +template <class ForwardIterator, class T, class Compare, class Distance> +inline ForwardIterator __upper_bound(ForwardIterator first, + ForwardIterator last, + const T& value, Compare comp, Distance*, + bidirectional_iterator_tag) { + return __upper_bound(first, last, value, comp, (Distance*)0, + forward_iterator_tag()); +} + +template <class RandomAccessIterator, class T, class Compare, class Distance> +RandomAccessIterator __upper_bound(RandomAccessIterator first, + RandomAccessIterator last, + const T& value, Compare comp, Distance*, + random_access_iterator_tag) { + Distance len = last - first; + Distance half; + RandomAccessIterator middle; + + while (len > 0) { + half = len / 2; + middle = first + half; + if (comp(value, *middle)) + len = half; + else { + first = middle + 1; + len = len - half - 1; + } + } + return first; +} + +template <class ForwardIterator, class T, class Compare> +inline ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, + const T& value, Compare comp) { + return __upper_bound(first, last, value, comp, distance_type(first), + iterator_category(first)); +} + +template <class ForwardIterator, class T, class Distance> +pair<ForwardIterator, ForwardIterator> +__equal_range(ForwardIterator first, ForwardIterator last, const T& value, + Distance*, forward_iterator_tag) { + Distance len = 0; + distance(first, last, len); + Distance half; + ForwardIterator middle, left, right; + + while (len > 0) { + half = len / 2; + middle = first; + advance(middle, half); + if (*middle < value) { + first = middle; + ++first; + len = len - half - 1; + } else if (value < *middle) + len = half; + else { + left = lower_bound(first, middle, value); + advance(first, len); + right = upper_bound(++middle, first, value); + return pair<ForwardIterator, ForwardIterator>(left, right); + } + } + return pair<ForwardIterator, ForwardIterator>(first, first); +} + +template <class ForwardIterator, class T, class Distance> +inline pair<ForwardIterator, ForwardIterator> +__equal_range(ForwardIterator first, ForwardIterator last, const T& value, + Distance*, bidirectional_iterator_tag) { + return __equal_range(first, last, value, (Distance*)0, + forward_iterator_tag()); +} + +template <class RandomAccessIterator, class T, class Distance> +pair<RandomAccessIterator, RandomAccessIterator> +__equal_range(RandomAccessIterator first, RandomAccessIterator last, + const T& value, Distance*, random_access_iterator_tag) { + Distance len = last - first; + Distance half; + RandomAccessIterator middle, left, right; + + while (len > 0) { + half = len / 2; + middle = first + half; + if (*middle < value) { + first = middle + 1; + len = len - half - 1; + } else if (value < *middle) + len = half; + else { + left = lower_bound(first, middle, value); + right = upper_bound(++middle, first + len, value); + return pair<RandomAccessIterator, RandomAccessIterator>(left, + right); + } + } + return pair<RandomAccessIterator, RandomAccessIterator>(first, first); +} + +template <class ForwardIterator, class T> +inline pair<ForwardIterator, ForwardIterator> +equal_range(ForwardIterator first, ForwardIterator last, const T& value) { + return __equal_range(first, last, value, distance_type(first), + iterator_category(first)); +} + +template <class ForwardIterator, class T, class Compare, class Distance> +pair<ForwardIterator, ForwardIterator> +__equal_range(ForwardIterator first, ForwardIterator last, const T& value, + Compare comp, Distance*, forward_iterator_tag) { + Distance len = 0; + distance(first, last, len); + Distance half; + ForwardIterator middle, left, right; + + while (len > 0) { + half = len / 2; + middle = first; + advance(middle, half); + if (comp(*middle, value)) { + first = middle; + ++first; + len = len - half - 1; + } else if (comp(value, *middle)) + len = half; + else { + left = lower_bound(first, middle, value, comp); + advance(first, len); + right = upper_bound(++middle, first, value, comp); + return pair<ForwardIterator, ForwardIterator>(left, right); + } + } + return pair<ForwardIterator, ForwardIterator>(first, first); +} + +template <class ForwardIterator, class T, class Compare, class Distance> +inline pair<ForwardIterator, ForwardIterator> +__equal_range(ForwardIterator first, ForwardIterator last, const T& value, + Compare comp, Distance*, bidirectional_iterator_tag) { + return __equal_range(first, last, value, comp, (Distance*)0, + forward_iterator_tag()); +} + +template <class RandomAccessIterator, class T, class Compare, class Distance> +pair<RandomAccessIterator, RandomAccessIterator> +__equal_range(RandomAccessIterator first, RandomAccessIterator last, + const T& value, Compare comp, Distance*, + random_access_iterator_tag) { + Distance len = last - first; + Distance half; + RandomAccessIterator middle, left, right; + + while (len > 0) { + half = len / 2; + middle = first + half; + if (comp(*middle, value)) { + first = middle + 1; + len = len - half - 1; + } else if (comp(value, *middle)) + len = half; + else { + left = lower_bound(first, middle, value, comp); + right = upper_bound(++middle, first + len, value, comp); + return pair<RandomAccessIterator, RandomAccessIterator>(left, + right); + } + } + return pair<RandomAccessIterator, RandomAccessIterator>(first, first); +} + +template <class ForwardIterator, class T, class Compare> +inline pair<ForwardIterator, ForwardIterator> +equal_range(ForwardIterator first, ForwardIterator last, const T& value, + Compare comp) { + return __equal_range(first, last, value, comp, distance_type(first), + iterator_category(first)); +} + +template <class ForwardIterator, class T> +bool binary_search(ForwardIterator first, ForwardIterator last, + const T& value) { + ForwardIterator i = lower_bound(first, last, value); + return i != last && !(value < *i); +} + +template <class ForwardIterator, class T, class Compare> +bool binary_search(ForwardIterator first, ForwardIterator last, const T& value, + Compare comp) { + ForwardIterator i = lower_bound(first, last, value, comp); + return i != last && !comp(value, *i); +} + +template <class InputIterator1, class InputIterator2, class OutputIterator> +OutputIterator merge(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + OutputIterator result) { + while (first1 != last1 && first2 != last2) { + if (*first2 < *first1) { + *result = *first2; + ++first2; + } + else { + *result = *first1; + ++first1; + } + ++result; + } + return copy(first2, last2, copy(first1, last1, result)); +} + +template <class InputIterator1, class InputIterator2, class OutputIterator, + class Compare> +OutputIterator merge(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + OutputIterator result, Compare comp) { + while (first1 != last1 && first2 != last2) { + if (comp(*first2, *first1)) { + *result = *first2; + ++first2; + } + else { + *result = *first1; + ++first1; + } + ++result; + } + return copy(first2, last2, copy(first1, last1, result)); +} + +template <class BidirectionalIterator, class Distance> +void __merge_without_buffer(BidirectionalIterator first, + BidirectionalIterator middle, + BidirectionalIterator last, + Distance len1, Distance len2) { + if (len1 == 0 || len2 == 0) return; + if (len1 + len2 == 2) { + if (*middle < *first) iter_swap(first, middle); + return; + } + BidirectionalIterator first_cut = first; + BidirectionalIterator second_cut = middle; + Distance len11 = 0; + Distance len22 = 0; + if (len1 > len2) { + len11 = len1 / 2; + advance(first_cut, len11); + second_cut = lower_bound(middle, last, *first_cut); + distance(middle, second_cut, len22); + } else { + len22 = len2 / 2; + advance(second_cut, len22); + first_cut = upper_bound(first, middle, *second_cut); + distance(first, first_cut, len11); + } + rotate(first_cut, middle, second_cut); + BidirectionalIterator new_middle = first_cut; + advance(new_middle, len22); + __merge_without_buffer(first, first_cut, new_middle, len11, len22); + __merge_without_buffer(new_middle, second_cut, last, len1 - len11, + len2 - len22); +} + +template <class BidirectionalIterator, class Distance, class Compare> +void __merge_without_buffer(BidirectionalIterator first, + BidirectionalIterator middle, + BidirectionalIterator last, + Distance len1, Distance len2, Compare comp) { + if (len1 == 0 || len2 == 0) return; + if (len1 + len2 == 2) { + if (comp(*middle, *first)) iter_swap(first, middle); + return; + } + BidirectionalIterator first_cut = first; + BidirectionalIterator second_cut = middle; + Distance len11 = 0; + Distance len22 = 0; + if (len1 > len2) { + len11 = len1 / 2; + advance(first_cut, len11); + second_cut = lower_bound(middle, last, *first_cut, comp); + distance(middle, second_cut, len22); + } else { + len22 = len2 / 2; + advance(second_cut, len22); + first_cut = upper_bound(first, middle, *second_cut, comp); + distance(first, first_cut, len11); + } + rotate(first_cut, middle, second_cut); + BidirectionalIterator new_middle = first_cut; + advance(new_middle, len22); + __merge_without_buffer(first, first_cut, new_middle, len11, len22, comp); + __merge_without_buffer(new_middle, second_cut, last, len1 - len11, + len2 - len22, comp); +} + +template <class BidirectionalIterator1, class BidirectionalIterator2, + class Distance> +BidirectionalIterator1 __rotate_adaptive(BidirectionalIterator1 first, + BidirectionalIterator1 middle, + BidirectionalIterator1 last, + Distance len1, Distance len2, + BidirectionalIterator2 buffer, + Distance buffer_size) { + BidirectionalIterator2 buffer_end; + if (len1 > len2 && len2 <= buffer_size) { + buffer_end = copy(middle, last, buffer); + copy_backward(first, middle, last); + return copy(buffer, buffer_end, first); + } else if (len1 <= buffer_size) { + buffer_end = copy(first, middle, buffer); + copy(middle, last, first); + return copy_backward(buffer, buffer_end, last); + } else { + rotate(first, middle, last); + advance(first, len2); + return first; + } +} + +template <class BidirectionalIterator1, class BidirectionalIterator2, + class BidirectionalIterator3> +BidirectionalIterator3 __merge_backward(BidirectionalIterator1 first1, + BidirectionalIterator1 last1, + BidirectionalIterator2 first2, + BidirectionalIterator2 last2, + BidirectionalIterator3 result) { + if (first1 == last1) return copy_backward(first2, last2, result); + if (first2 == last2) return copy_backward(first1, last1, result); + --last1; + --last2; + while (true) { + if (*last2 < *last1) { + *--result = *last1; + if (first1 == last1) return copy_backward(first2, ++last2, result); + --last1; + } else { + *--result = *last2; + if (first2 == last2) return copy_backward(first1, ++last1, result); + --last2; + } + } +} + +template <class BidirectionalIterator1, class BidirectionalIterator2, + class BidirectionalIterator3, class Compare> +BidirectionalIterator3 __merge_backward(BidirectionalIterator1 first1, + BidirectionalIterator1 last1, + BidirectionalIterator2 first2, + BidirectionalIterator2 last2, + BidirectionalIterator3 result, + Compare comp) { + if (first1 == last1) return copy_backward(first2, last2, result); + if (first2 == last2) return copy_backward(first1, last1, result); + --last1; + --last2; + while (true) { + if (comp(*last2, *last1)) { + *--result = *last1; + if (first1 == last1) return copy_backward(first2, ++last2, result); + --last1; + } else { + *--result = *last2; + if (first2 == last2) return copy_backward(first1, ++last1, result); + --last2; + } + } +} + +template <class BidirectionalIterator, class Distance, class Pointer> +void __merge_adaptive(BidirectionalIterator first, + BidirectionalIterator middle, + BidirectionalIterator last, Distance len1, Distance len2, + Pointer buffer, Distance buffer_size) { + if (len1 <= len2 && len1 <= buffer_size) { + Pointer end_buffer = copy(first, middle, buffer); + merge(buffer, end_buffer, middle, last, first); + } else if (len2 <= buffer_size) { + Pointer end_buffer = copy(middle, last, buffer); + __merge_backward(first, middle, buffer, end_buffer, last); + } else { + BidirectionalIterator first_cut = first; + BidirectionalIterator second_cut = middle; + Distance len11 = 0; + Distance len22 = 0; + if (len1 > len2) { + len11 = len1 / 2; + advance(first_cut, len11); + second_cut = lower_bound(middle, last, *first_cut); + distance(middle, second_cut, len22); + } else { + len22 = len2 / 2; + advance(second_cut, len22); + first_cut = upper_bound(first, middle, *second_cut); + distance(first, first_cut, len11); + } + BidirectionalIterator new_middle = + __rotate_adaptive(first_cut, middle, second_cut, len1 - len11, + len22, buffer, buffer_size); + __merge_adaptive(first, first_cut, new_middle, len11, len22, buffer, + buffer_size); + __merge_adaptive(new_middle, second_cut, last, len1 - len11, + len2 - len22, buffer, buffer_size); + } +} + +template <class BidirectionalIterator, class Distance, class Pointer, + class Compare> +void __merge_adaptive(BidirectionalIterator first, + BidirectionalIterator middle, + BidirectionalIterator last, Distance len1, Distance len2, + Pointer buffer, Distance buffer_size, Compare comp) { + if (len1 <= len2 && len1 <= buffer_size) { + Pointer end_buffer = copy(first, middle, buffer); + merge(buffer, end_buffer, middle, last, first, comp); + } else if (len2 <= buffer_size) { + Pointer end_buffer = copy(middle, last, buffer); + __merge_backward(first, middle, buffer, end_buffer, last, comp); + } else { + BidirectionalIterator first_cut = first; + BidirectionalIterator second_cut = middle; + Distance len11 = 0; + Distance len22 = 0; + if (len1 > len2) { + len11 = len1 / 2; + advance(first_cut, len11); + second_cut = lower_bound(middle, last, *first_cut, comp); + distance(middle, second_cut, len22); + } else { + len22 = len2 / 2; + advance(second_cut, len22); + first_cut = upper_bound(first, middle, *second_cut, comp); + distance(first, first_cut, len11); + } + BidirectionalIterator new_middle = + __rotate_adaptive(first_cut, middle, second_cut, len1 - len11, + len22, buffer, buffer_size); + __merge_adaptive(first, first_cut, new_middle, len11, len22, buffer, + buffer_size, comp); + __merge_adaptive(new_middle, second_cut, last, len1 - len11, + len2 - len22, buffer, buffer_size, comp); + } +} + +template <class BidirectionalIterator, class T, class Distance> +inline void __inplace_merge_aux(BidirectionalIterator first, + BidirectionalIterator middle, + BidirectionalIterator last, T*, Distance*) { + Distance len1 = 0; + distance(first, middle, len1); + Distance len2 = 0; + distance(middle, last, len2); + + temporary_buffer<BidirectionalIterator, T> buf(first, last); + if (buf.begin() == 0) + __merge_without_buffer(first, middle, last, len1, len2); + else + __merge_adaptive(first, middle, last, len1, len2, + buf.begin(), Distance(buf.size())); +} + +template <class BidirectionalIterator, class T, class Distance, class Compare> +inline void __inplace_merge_aux(BidirectionalIterator first, + BidirectionalIterator middle, + BidirectionalIterator last, T*, Distance*, + Compare comp) { + Distance len1 = 0; + distance(first, middle, len1); + Distance len2 = 0; + distance(middle, last, len2); + + temporary_buffer<BidirectionalIterator, T> buf(first, last); + if (buf.begin() == 0) + __merge_without_buffer(first, middle, last, len1, len2, comp); + else + __merge_adaptive(first, middle, last, len1, len2, + buf.begin(), Distance(buf.size()), + comp); +} + +template <class BidirectionalIterator> +inline void inplace_merge(BidirectionalIterator first, + BidirectionalIterator middle, + BidirectionalIterator last) { + if (first == middle || middle == last) return; + __inplace_merge_aux(first, middle, last, value_type(first), + distance_type(first)); +} + +template <class BidirectionalIterator, class Compare> +inline void inplace_merge(BidirectionalIterator first, + BidirectionalIterator middle, + BidirectionalIterator last, Compare comp) { + if (first == middle || middle == last) return; + __inplace_merge_aux(first, middle, last, value_type(first), + distance_type(first), comp); +} + +template <class InputIterator1, class InputIterator2> +bool includes(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2) { + while (first1 != last1 && first2 != last2) + if (*first2 < *first1) + return false; + else if(*first1 < *first2) + ++first1; + else + ++first1, ++first2; + + return first2 == last2; +} + +template <class InputIterator1, class InputIterator2, class Compare> +bool includes(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, Compare comp) { + while (first1 != last1 && first2 != last2) + if (comp(*first2, *first1)) + return false; + else if(comp(*first1, *first2)) + ++first1; + else + ++first1, ++first2; + + return first2 == last2; +} + +template <class InputIterator1, class InputIterator2, class OutputIterator> +OutputIterator set_union(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + OutputIterator result) { + while (first1 != last1 && first2 != last2) { + if (*first1 < *first2) { + *result = *first1; + ++first1; + } + else if (*first2 < *first1) { + *result = *first2; + ++first2; + } + else { + *result = *first1; + ++first1; + ++first2; + } + ++result; + } + return copy(first2, last2, copy(first1, last1, result)); +} + +template <class InputIterator1, class InputIterator2, class OutputIterator, + class Compare> +OutputIterator set_union(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + OutputIterator result, Compare comp) { + while (first1 != last1 && first2 != last2) { + if (comp(*first1, *first2)) { + *result = *first1; + ++first1; + } + else if (comp(*first2, *first1)) { + *result = *first2; + ++first2; + } + else { + *result = *first1; + ++first1; + ++first2; + } + ++result; + } + return copy(first2, last2, copy(first1, last1, result)); +} + +template <class InputIterator1, class InputIterator2, class OutputIterator> +OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + OutputIterator result) { + while (first1 != last1 && first2 != last2) + if (*first1 < *first2) + ++first1; + else if (*first2 < *first1) + ++first2; + else { + *result = *first1; + ++first1; + ++first2; + ++result; + } + return result; +} + +template <class InputIterator1, class InputIterator2, class OutputIterator, + class Compare> +OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + OutputIterator result, Compare comp) { + while (first1 != last1 && first2 != last2) + if (comp(*first1, *first2)) + ++first1; + else if (comp(*first2, *first1)) + ++first2; + else { + *result = *first1; + ++first1; + ++first2; + ++result; + } + return result; +} + +template <class InputIterator1, class InputIterator2, class OutputIterator> +OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + OutputIterator result) { + while (first1 != last1 && first2 != last2) + if (*first1 < *first2) { + *result = *first1; + ++first1; + ++result; + } + else if (*first2 < *first1) + ++first2; + else { + ++first1; + ++first2; + } + return copy(first1, last1, result); +} + +template <class InputIterator1, class InputIterator2, class OutputIterator, + class Compare> +OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + OutputIterator result, Compare comp) { + while (first1 != last1 && first2 != last2) + if (comp(*first1, *first2)) { + *result = *first1; + ++first1; + ++result; + } + else if (comp(*first2, *first1)) + ++first2; + else { + ++first1; + ++first2; + } + return copy(first1, last1, result); +} + +template <class InputIterator1, class InputIterator2, class OutputIterator> +OutputIterator set_symmetric_difference(InputIterator1 first1, + InputIterator1 last1, + InputIterator2 first2, + InputIterator2 last2, + OutputIterator result) { + while (first1 != last1 && first2 != last2) + if (*first1 < *first2) { + *result = *first1; + ++first1; + ++result; + } + else if (*first2 < *first1) { + *result = *first2; + ++first2; + ++result; + } + else { + ++first1; + ++first2; + } + return copy(first2, last2, copy(first1, last1, result)); +} + +template <class InputIterator1, class InputIterator2, class OutputIterator, + class Compare> +OutputIterator set_symmetric_difference(InputIterator1 first1, + InputIterator1 last1, + InputIterator2 first2, + InputIterator2 last2, + OutputIterator result, Compare comp) { + while (first1 != last1 && first2 != last2) + if (comp(*first1, *first2)) { + *result = *first1; + ++first1; + ++result; + } + else if (comp(*first2, *first1)) { + *result = *first2; + ++first2; + ++result; + } + else { + ++first1; + ++first2; + } + return copy(first2, last2, copy(first1, last1, result)); +} + +template <class ForwardIterator> +ForwardIterator max_element(ForwardIterator first, ForwardIterator last) { + if (first == last) return first; + ForwardIterator result = first; + while (++first != last) + if (*result < *first) result = first; + return result; +} + +template <class ForwardIterator, class Compare> +ForwardIterator max_element(ForwardIterator first, ForwardIterator last, + Compare comp) { + if (first == last) return first; + ForwardIterator result = first; + while (++first != last) + if (comp(*result, *first)) result = first; + return result; +} + +template <class ForwardIterator> +ForwardIterator min_element(ForwardIterator first, ForwardIterator last) { + if (first == last) return first; + ForwardIterator result = first; + while (++first != last) + if (*first < *result) result = first; + return result; +} + +template <class ForwardIterator, class Compare> +ForwardIterator min_element(ForwardIterator first, ForwardIterator last, + Compare comp) { + if (first == last) return first; + ForwardIterator result = first; + while (++first != last) + if (comp(*first, *result)) result = first; + return result; +} + +template <class BidirectionalIterator> +bool next_permutation(BidirectionalIterator first, + BidirectionalIterator last) { + if (first == last) return false; + BidirectionalIterator i = first; + ++i; + if (i == last) return false; + i = last; + --i; + + for(;;) { + BidirectionalIterator ii = i; + --i; + if (*i < *ii) { + BidirectionalIterator j = last; + while (!(*i < *--j)); + iter_swap(i, j); + reverse(ii, last); + return true; + } + if (i == first) { + reverse(first, last); + return false; + } + } +} + +template <class BidirectionalIterator, class Compare> +bool next_permutation(BidirectionalIterator first, BidirectionalIterator last, + Compare comp) { + if (first == last) return false; + BidirectionalIterator i = first; + ++i; + if (i == last) return false; + i = last; + --i; + + for(;;) { + BidirectionalIterator ii = i; + --i; + if (comp(*i, *ii)) { + BidirectionalIterator j = last; + while (!comp(*i, *--j)); + iter_swap(i, j); + reverse(ii, last); + return true; + } + if (i == first) { + reverse(first, last); + return false; + } + } +} + +template <class BidirectionalIterator> +bool prev_permutation(BidirectionalIterator first, + BidirectionalIterator last) { + if (first == last) return false; + BidirectionalIterator i = first; + ++i; + if (i == last) return false; + i = last; + --i; + + for(;;) { + BidirectionalIterator ii = i; + --i; + if (*ii < *i) { + BidirectionalIterator j = last; + while (!(*--j < *i)); + iter_swap(i, j); + reverse(ii, last); + return true; + } + if (i == first) { + reverse(first, last); + return false; + } + } +} + +template <class BidirectionalIterator, class Compare> +bool prev_permutation(BidirectionalIterator first, BidirectionalIterator last, + Compare comp) { + if (first == last) return false; + BidirectionalIterator i = first; + ++i; + if (i == last) return false; + i = last; + --i; + + for(;;) { + BidirectionalIterator ii = i; + --i; + if (comp(*ii, *i)) { + BidirectionalIterator j = last; + while (!comp(*--j, *i)); + iter_swap(i, j); + reverse(ii, last); + return true; + } + if (i == first) { + reverse(first, last); + return false; + } + } +} + +template <class InputIterator, class T> +T accumulate(InputIterator first, InputIterator last, T init) { + for ( ; first != last; ++first) + init = init + *first; + return init; +} + +template <class InputIterator, class T, class BinaryOperation> +T accumulate(InputIterator first, InputIterator last, T init, + BinaryOperation binary_op) { + for ( ; first != last; ++first) + init = binary_op(init, *first); + return init; +} + +template <class InputIterator1, class InputIterator2, class T> +T inner_product(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, T init) { + for ( ; first1 != last1; ++first1, ++first2) + init = init + (*first1 * *first2); + return init; +} + +template <class InputIterator1, class InputIterator2, class T, + class BinaryOperation1, class BinaryOperation2> +T inner_product(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, T init, BinaryOperation1 binary_op1, + BinaryOperation2 binary_op2) { + for ( ; first1 != last1; ++first1, ++first2) + init = binary_op1(init, binary_op2(*first1, *first2)); + return init; +} + +template <class InputIterator, class OutputIterator, class T> +OutputIterator __partial_sum(InputIterator first, InputIterator last, + OutputIterator result, T*) { + T value = *first; + while (++first != last) { + value = value + *first; + *++result = value; + } + return ++result; +} + +template <class InputIterator, class OutputIterator> +OutputIterator partial_sum(InputIterator first, InputIterator last, + OutputIterator result) { + if (first == last) return result; + *result = *first; + return __partial_sum(first, last, result, value_type(first)); +} + +template <class InputIterator, class OutputIterator, class T, + class BinaryOperation> +OutputIterator __partial_sum(InputIterator first, InputIterator last, + OutputIterator result, T*, + BinaryOperation binary_op) { + T value = *first; + while (++first != last) { + value = binary_op(value, *first); + *++result = value; + } + return ++result; +} + +template <class InputIterator, class OutputIterator, class BinaryOperation> +OutputIterator partial_sum(InputIterator first, InputIterator last, + OutputIterator result, BinaryOperation binary_op) { + if (first == last) return result; + *result = *first; + return __partial_sum(first, last, result, value_type(first), binary_op); +} + +template <class InputIterator, class OutputIterator, class T> +OutputIterator __adjacent_difference(InputIterator first, InputIterator last, + OutputIterator result, T*) { + T value = *first; + while (++first != last) { + T tmp = *first; + *++result = tmp - value; + value = tmp; + } + return ++result; +} + +template <class InputIterator, class OutputIterator> +OutputIterator adjacent_difference(InputIterator first, InputIterator last, + OutputIterator result) { + if (first == last) return result; + *result = *first; + return __adjacent_difference(first, last, result, value_type(first)); +} + +template <class InputIterator, class OutputIterator, class T, + class BinaryOperation> +OutputIterator __adjacent_difference(InputIterator first, InputIterator last, + OutputIterator result, T*, + BinaryOperation binary_op) { + T value = *first; + while (++first != last) { + T tmp = *first; + *++result = binary_op(tmp, value); + value = tmp; + } + return ++result; +} + +template <class InputIterator, class OutputIterator, class BinaryOperation> +OutputIterator adjacent_difference(InputIterator first, InputIterator last, + OutputIterator result, + BinaryOperation binary_op) { + if (first == last) return result; + *result = *first; + return __adjacent_difference(first, last, result, value_type(first), + binary_op); +} + +// Returns x ** n, where n >= 0. Note that "multiplication" +// is required to be associative, but not necessarily commutative. + +template <class T, class Integer, class MonoidOperation> +T power(T x, Integer n, MonoidOperation op) { + if (n == 0) + return identity_element(op); + else { + while (n % 2 == 0) { + n /= 2; + x = op(x, x); + } + + T result = x; + n /= 2; + while (n != 0) { + x = op(x, x); + if (n % 2 != 0) + result = op(result, x); + n /= 2; + } + return result; + } +} + +template <class T, class Integer> +inline T power(T x, Integer n) { + return power(x, n, multiplies<T>()); +} + + +template <class ForwardIterator, class T> +void iota(ForwardIterator first, ForwardIterator last, T value) { + while (first != last) *first++ = value++; +} + +template <class RandomAccessIterator, class Distance> +bool __is_heap(RandomAccessIterator first, RandomAccessIterator last, + Distance*) +{ + const Distance n = last - first; + + Distance parent = 0; + for (Distance child = 1; child < n; ++child) { + if (first[parent] < first[child]) + return false; + if (child % 2 == 0) + ++parent; + } + return true; +} + +template <class RandomAccessIterator> +inline bool is_heap(RandomAccessIterator first, RandomAccessIterator last) +{ + return __is_heap(first, last, distance_type(first)); +} + + +template <class RandomAccessIterator, class Distance, class StrictWeakOrdering> +bool __is_heap(RandomAccessIterator first, RandomAccessIterator last, + StrictWeakOrdering comp, + Distance*) +{ + const Distance n = last - first; + + Distance parent = 0; + for (Distance child = 1; child < n; ++child) { + if (comp(first[parent], first[child])) + return false; + if (child % 2 == 0) + ++parent; + } + return true; +} + +template <class RandomAccessIterator, class StrictWeakOrdering> +inline bool is_heap(RandomAccessIterator first, RandomAccessIterator last, + StrictWeakOrdering comp) +{ + return __is_heap(first, last, comp, distance_type(first)); +} + + +template <class ForwardIterator> +bool is_sorted(ForwardIterator first, ForwardIterator last) +{ + if (first == last) + return true; + + ForwardIterator next = first; + for (++next; next != last; first = next, ++next) { + if (*next < *first) + return false; + } + + return true; +} + +template <class ForwardIterator, class StrictWeakOrdering> +bool is_sorted(ForwardIterator first, ForwardIterator last, + StrictWeakOrdering comp) +{ + if (first == last) + return true; + + ForwardIterator next = first; + for (++next; next != last; first = next, ++next) { + if (comp(*next, *first)) + return false; + } + + return true; +} + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma reset woff 1209 +#endif + +#endif /* __SGI_STL_ALGO_H */ diff --git a/libstdc++/stl/algobase.h b/libstdc++/stl/algobase.h new file mode 100644 index 0000000..0a17f48 --- /dev/null +++ b/libstdc++/stl/algobase.h @@ -0,0 +1,841 @@ +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#ifndef _SGI_STL_ALGOBASE_H +#define _SGI_STL_ALGOBASE_H + +#include <string.h> +#include <limits.h> +#include <function.h> +#include <pair.h> +#include <iterator.h> +#include <new.h> +#include <type_traits.h> + +template <class ForwardIterator1, class ForwardIterator2, class T> +inline void __iter_swap(ForwardIterator1 a, ForwardIterator2 b, T*) { + T tmp = *a; + *a = *b; + *b = tmp; +} + +template <class ForwardIterator1, class ForwardIterator2> +inline void iter_swap(ForwardIterator1 a, ForwardIterator2 b) { + __iter_swap(a, b, value_type(a)); +} + +template <class T> +inline void swap(T& a, T& b) { + T tmp = a; + a = b; + b = tmp; +} + +#ifdef __BORLANDC__ +#include <stdlib.h> +#else + +template <class T> +inline const T& min(const T& a, const T& b) { + return b < a ? b : a; +} + +template <class T> +inline const T& max(const T& a, const T& b) { + return a < b ? b : a; +} + +#endif + +template <class T, class Compare> +inline const T& min(const T& a, const T& b, Compare comp) { + return comp(b, a) ? b : a; +} + +template <class T, class Compare> +inline const T& max(const T& a, const T& b, Compare comp) { + return comp(a, b) ? b : a; +} + +template <class InputIterator, class Distance> +inline void __distance(InputIterator first, InputIterator last, Distance& n, + input_iterator_tag) { + while (first != last) { ++first; ++n; } +} + +template <class ForwardIterator, class Distance> +inline void __distance(ForwardIterator first, ForwardIterator last, + Distance& n, + forward_iterator_tag) { + while (first != last) { ++first; ++n; } +} + +template <class BidirectionalIterator, class Distance> +inline void __distance(BidirectionalIterator first, BidirectionalIterator last, + Distance& n, bidirectional_iterator_tag) { + while (first != last) { ++first; ++n; } +} + +template <class RandomAccessIterator, class Distance> +inline void __distance(RandomAccessIterator first, RandomAccessIterator last, + Distance& n, random_access_iterator_tag) { + n += last - first; +} + +template <class InputIterator, class Distance> +inline void distance(InputIterator first, InputIterator last, Distance& n) { + __distance(first, last, n, iterator_category(first)); +} + +#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION + +template <class InputIterator> +inline iterator_traits<InputIterator>::difference_type +__distance(InputIterator first, InputIterator last, input_iterator_tag) { + iterator_traits<InputIterator>::difference_type n = 0; + while (first != last) { + ++first; ++n; + } + return n; +} + +template <class ForwardIterator> +inline iterator_traits<ForwardIterator>::difference_type +__distance(ForwardIterator first, ForwardIterator last, forward_iterator_tag) { + return __distance(first, last, input_iterator_tag()); +} + +template <class BidirectionalIterator> +inline iterator_traits<BidirectionalIterator>::difference_type +__distance(BidirectionalIterator first, BidirectionalIterator last, + bidirectional_iterator_tag) { + return __distance(first, last, input_iterator_tag()); +} + +template <class RandomAccessIterator> +inline iterator_traits<RandomAccessIterator>::difference_type +__distance(RandomAccessIterator first, RandomAccessIterator last, + random_access_iterator_tag) { + return last - first; +} + +template <class InputIterator> +inline iterator_traits<InputIterator>::difference_type +distance(InputIterator first, InputIterator last) { + return __distance(first, last, + iterator_traits<InputIterator>::iterator_category()); +} + +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +template <class InputIterator, class Distance> +inline void __advance(InputIterator& i, Distance n, input_iterator_tag) { + while (n--) ++i; +} + +template <class ForwardIterator, class Distance> +inline void __advance(ForwardIterator& i, Distance n, forward_iterator_tag) { + while (n--) ++i; +} + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma set woff 1183 +#endif + +template <class BidirectionalIterator, class Distance> +inline void __advance(BidirectionalIterator& i, Distance n, + bidirectional_iterator_tag) { + if (n >= 0) + while (n--) ++i; + else + while (n++) --i; +} + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma reset woff 1183 +#endif + +template <class RandomAccessIterator, class Distance> +inline void __advance(RandomAccessIterator& i, Distance n, + random_access_iterator_tag) { + i += n; +} + +template <class InputIterator, class Distance> +inline void advance(InputIterator& i, Distance n) { + __advance(i, n, iterator_category(i)); +} + +template <class InputIterator, class OutputIterator> +inline OutputIterator __copy(InputIterator first, InputIterator last, + OutputIterator result, input_iterator_tag) +{ + for ( ; first != last; ++result, ++first) + *result = *first; + return result; +} + +template <class InputIterator, class OutputIterator> +inline OutputIterator __copy(InputIterator first, InputIterator last, + OutputIterator result, forward_iterator_tag) +{ + return __copy(first, last, result, input_iterator_tag()); +} + +template <class InputIterator, class OutputIterator> +inline OutputIterator __copy(InputIterator first, InputIterator last, + OutputIterator result, bidirectional_iterator_tag) +{ + return __copy(first, last, result, input_iterator_tag()); +} + +template <class RandomAccessIterator, class OutputIterator, class Distance> +inline OutputIterator +__copy_d(RandomAccessIterator first, RandomAccessIterator last, + OutputIterator result, Distance*) +{ + for (Distance n = last - first; n > 0; --n, ++result, ++first) + *result = *first; + return result; +} + +template <class RandomAccessIterator, class OutputIterator> +inline OutputIterator +__copy(RandomAccessIterator first, RandomAccessIterator last, + OutputIterator result, random_access_iterator_tag) +{ + return __copy_d(first, last, result, distance_type(first)); +} + +template <class InputIterator, class OutputIterator> +struct __copy_dispatch +{ + OutputIterator operator()(InputIterator first, InputIterator last, + OutputIterator result) { + return __copy(first, last, result, iterator_category(first)); + } +}; + +#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION + +template <class T> +inline T* __copy_t(const T* first, const T* last, T* result, __true_type) { + memmove(result, first, sizeof(T) * (last - first)); + return result + (last - first); +} + +template <class T> +inline T* __copy_t(const T* first, const T* last, T* result, __false_type) { + return __copy_d(first, last, result, (ptrdiff_t*) 0); +} + +template <class T> +struct __copy_dispatch<T*, T*> +{ + T* operator()(T* first, T* last, T* result) { + return __copy_t(first, last, result, + __type_traits<T>::has_trivial_assignment_operator()); + } +}; + +template <class T> +struct __copy_dispatch<const T*, T*> +{ + T* operator()(const T* first, const T* last, T* result) { + return __copy_t(first, last, result, + __type_traits<T>::has_trivial_assignment_operator()); + } +}; + +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +template <class InputIterator, class OutputIterator> +inline OutputIterator copy(InputIterator first, InputIterator last, + OutputIterator result) +{ + return __copy_dispatch<InputIterator,OutputIterator>()(first, last, result); +} + +inline char* copy(const char* first, const char* last, char* result) { + memmove(result, first, last - first); + return result + (last - first); +} + +inline wchar_t* copy(const wchar_t* first, const wchar_t* last, + wchar_t* result) { + memmove(result, first, sizeof(wchar_t) * (last - first)); + return result + (last - first); +} + +template <class BidirectionalIterator1, class BidirectionalIterator2> +inline BidirectionalIterator2 __copy_backward(BidirectionalIterator1 first, + BidirectionalIterator1 last, + BidirectionalIterator2 result) { + while (first != last) *--result = *--last; + return result; +} + + +template <class BidirectionalIterator1, class BidirectionalIterator2> +struct __copy_backward_dispatch +{ + BidirectionalIterator2 operator()(BidirectionalIterator1 first, + BidirectionalIterator1 last, + BidirectionalIterator2 result) { + return __copy_backward(first, last, result); + } +}; + +#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION + +template <class T> +inline T* __copy_backward_t(const T* first, const T* last, T* result, + __true_type) { + const ptrdiff_t N = last - first; + memmove(result - N, first, sizeof(T) * N); + return result - N; +} + +template <class T> +inline T* __copy_backward_t(const T* first, const T* last, T* result, + __false_type) { + return __copy_backward(first, last, result); +} + +template <class T> +struct __copy_backward_dispatch<T*, T*> +{ + T* operator()(T* first, T* last, T* result) { + return + __copy_backward_t(first, last, result, + __type_traits<T>::has_trivial_assignment_operator()); + } +}; + +template <class T> +struct __copy_backward_dispatch<const T*, T*> +{ + T* operator()(const T* first, const T* last, T* result) { + return + __copy_backward_t(first, last, result, + __type_traits<T>::has_trivial_assignment_operator()); + } +}; + +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +template <class BidirectionalIterator1, class BidirectionalIterator2> +inline BidirectionalIterator2 copy_backward(BidirectionalIterator1 first, + BidirectionalIterator1 last, + BidirectionalIterator2 result) { + return __copy_backward_dispatch<BidirectionalIterator1, + BidirectionalIterator2>()(first, last, + result); +} + +template <class InputIterator, class Size, class OutputIterator> +OutputIterator __copy_n(InputIterator first, Size count, + OutputIterator result, + input_iterator_tag) { + for ( ; count > 0; --count, ++first, ++result) + *result = *first; + return result; +} + +template <class ForwardIterator, class Size, class OutputIterator> +inline OutputIterator __copy_n(ForwardIterator first, Size count, + OutputIterator result, + forward_iterator_tag) { + return __copy_n(first, count, result, input_iterator_tag()); +} + +template <class BidirectionalIterator, class Size, class OutputIterator> +inline OutputIterator __copy_n(BidirectionalIterator first, Size count, + OutputIterator result, + bidirectional_iterator_tag) { + return __copy_n(first, count, result, input_iterator_tag()); +} + +template <class RandomAccessIterator, class Size, class OutputIterator> +inline OutputIterator __copy_n(RandomAccessIterator first, Size count, + OutputIterator result, + random_access_iterator_tag) { + return copy(first, first + count, result); +} + +template <class InputIterator, class Size, class OutputIterator> +inline OutputIterator copy_n(InputIterator first, Size count, + OutputIterator result) { + return __copy_n(first, count, result, iterator_category(first)); +} + +template <class ForwardIterator, class T> +void fill(ForwardIterator first, ForwardIterator last, const T& value) { + for ( ; first != last; ++first) + *first = value; +} + +template <class OutputIterator, class Size, class T> +OutputIterator fill_n(OutputIterator first, Size n, const T& value) { + for ( ; n > 0; --n, ++first) + *first = value; + return first; +} + +template <class InputIterator1, class InputIterator2> +pair<InputIterator1, InputIterator2> mismatch(InputIterator1 first1, + InputIterator1 last1, + InputIterator2 first2) { + while (first1 != last1 && *first1 == *first2) { + ++first1; + ++first2; + } + return pair<InputIterator1, InputIterator2>(first1, first2); +} + +template <class InputIterator1, class InputIterator2, class BinaryPredicate> +pair<InputIterator1, InputIterator2> mismatch(InputIterator1 first1, + InputIterator1 last1, + InputIterator2 first2, + BinaryPredicate binary_pred) { + while (first1 != last1 && binary_pred(*first1, *first2)) { + ++first1; + ++first2; + } + return pair<InputIterator1, InputIterator2>(first1, first2); +} + +template <class InputIterator1, class InputIterator2> +inline bool equal(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2) { + for ( ; first1 != last1; ++first1, ++first2) + if (*first1 != *first2) + return false; + return true; +} + +template <class InputIterator1, class InputIterator2, class BinaryPredicate> +inline bool equal(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, BinaryPredicate binary_pred) { + for ( ; first1 != last1; ++first1, ++first2) + if (!binary_pred(*first1, *first2)) + return false; + return true; +} + +template <class InputIterator1, class InputIterator2> +bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2) { + for ( ; first1 != last1 && first2 != last2; ++first1, ++first2) { + if (*first1 < *first2) + return true; + if (*first2 < *first1) + return false; + } + return first1 == last1 && first2 != last2; +} + +template <class InputIterator1, class InputIterator2, class Compare> +bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + Compare comp) { + for ( ; first1 != last1 && first2 != last2; ++first1, ++first2) { + if (comp(*first1, *first2)) + return true; + if (comp(*first2, *first1)) + return false; + } + return first1 == last1 && first2 != last2; +} + +inline bool +lexicographical_compare(const unsigned char* first1, + const unsigned char* last1, + const unsigned char* first2, + const unsigned char* last2) +{ + const size_t len1 = last1 - first1; + const size_t len2 = last2 - first2; + const int result = memcmp(first1, first2, min(len1, len2)); + return result != 0 ? result < 0 : len1 < len2; +} + +inline bool lexicographical_compare(const char* first1, const char* last1, + const char* first2, const char* last2) +{ +#if CHAR_MAX == SCHAR_MAX + return lexicographical_compare((const signed char*) first1, + (const signed char*) last1, + (const signed char*) first2, + (const signed char*) last2); +#else + return lexicographical_compare((const unsigned char*) first1, + (const unsigned char*) last1, + (const unsigned char*) first2, + (const unsigned char*) last2); +#endif +} + +template <class InputIterator1, class InputIterator2> +int lexicographical_compare_3way(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2) +{ + while (first1 != last1 && first2 != last2) { + if (*first1 < *first2) return -1; + if (*first2 < *first1) return 1; + ++first1; ++first2; + } + if (first2 == last2) { + return !(first1 == last1); + } else { + return -1; + } +} + +inline int +lexicographical_compare_3way(const unsigned char* first1, + const unsigned char* last1, + const unsigned char* first2, + const unsigned char* last2) +{ + const int len1 = last1 - first1; + const int len2 = last2 - first2; + const int result = memcmp(first1, first2, min(len1, len2)); + return result == 0 ? len1 - len2 : result; +} + +inline int lexicographical_compare_3way(const char* first1, const char* last1, + const char* first2, const char* last2) +{ +#if CHAR_MAX == SCHAR_MAX + return lexicographical_compare_3way( + (const signed char*) first1, + (const signed char*) last1, + (const signed char*) first2, + (const signed char*) last2); +#else + return lexicographical_compare_3way((const unsigned char*) first1, + (const unsigned char*) last1, + (const unsigned char*) first2, + (const unsigned char*) last2); +#endif +} + +template <class T> +inline void destroy(T* pointer) { + pointer->~T(); +} + +template <class T1, class T2> +inline void construct(T1* p, const T2& value) { + new (p) T1(value); +} + +template <class ForwardIterator> +inline void +__destroy_aux(ForwardIterator first, ForwardIterator last, __false_type) { + for ( ; first < last; ++first) + destroy(&*first); +} + +template <class ForwardIterator> +inline void __destroy_aux(ForwardIterator, ForwardIterator, __true_type) { +} + +template <class ForwardIterator, class T> +inline void __destroy(ForwardIterator first, ForwardIterator last, T*) { + __destroy_aux(first, last, __type_traits<T>::has_trivial_destructor()); +} + +template <class ForwardIterator> +inline void destroy(ForwardIterator first, ForwardIterator last) { + __destroy(first, last, value_type(first)); +} + +inline void destroy(char*, char*) {} +inline void destroy(wchar_t*, wchar_t*) {} + +// Valid if copy construction is equivalent to assignment, and if the +// destructor is trivial. +template <class InputIterator, class ForwardIterator> +inline ForwardIterator +__uninitialized_copy_aux(InputIterator first, InputIterator last, + ForwardIterator result, + __true_type) { + return copy(first, last, result); +} + +template <class InputIterator, class ForwardIterator> +ForwardIterator +__uninitialized_copy_aux(InputIterator first, InputIterator last, + ForwardIterator result, + __false_type) { + ForwardIterator cur = result; +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + for ( ; first != last; ++first, ++cur) + construct(&*cur, *first); + return cur; +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy(result, cur); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ +} + + +template <class InputIterator, class ForwardIterator, class T> +inline ForwardIterator +__uninitialized_copy(InputIterator first, InputIterator last, + ForwardIterator result, T*) { + return __uninitialized_copy_aux(first, last, result, + __type_traits<T>::is_POD_type()); +} + +template <class InputIterator, class ForwardIterator> +inline ForwardIterator + uninitialized_copy(InputIterator first, InputIterator last, + ForwardIterator result) { + return __uninitialized_copy(first, last, result, value_type(result)); +} + +inline char* uninitialized_copy(const char* first, const char* last, + char* result) { + memmove(result, first, last - first); + return result + (last - first); +} + +inline wchar_t* uninitialized_copy(const wchar_t* first, const wchar_t* last, + wchar_t* result) { + memmove(result, first, sizeof(wchar_t) * (last - first)); + return result + (last - first); +} + +template <class InputIterator, class Size, class ForwardIterator> +ForwardIterator __uninitialized_copy_n(InputIterator first, Size count, + ForwardIterator result, + input_iterator_tag) { + ForwardIterator cur = result; +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + for ( ; count > 0 ; --count, ++first, ++cur) + construct(&*cur, *first); + return cur; +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy(result, cur); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ +} + +template <class ForwardIterator1, class Size, class ForwardIterator> +inline ForwardIterator +__uninitialized_copy_n(ForwardIterator1 first, Size count, + ForwardIterator result, + forward_iterator_tag) { + return __uninitialized_copy_n(first, count, result, input_iterator_tag()); +} + +template <class BidirectionalIterator, class Size, class ForwardIterator> +inline ForwardIterator +__uninitialized_copy_n(BidirectionalIterator first, Size count, + ForwardIterator result, + bidirectional_iterator_tag) { + return __uninitialized_copy_n(first, count, result, input_iterator_tag()); +} + +template <class RandomAccessIterator, class Size, class ForwardIterator> +inline ForwardIterator +__uninitialized_copy_n(RandomAccessIterator first, Size count, + ForwardIterator result, + random_access_iterator_tag) { + return uninitialized_copy(first, first + count, result); +} + +template <class InputIterator, class Size, class ForwardIterator> +inline ForwardIterator uninitialized_copy_n(InputIterator first, Size count, + ForwardIterator result) { + return __uninitialized_copy_n(first, count, result, + iterator_category(first)); +} + +// Valid if copy construction is equivalent to assignment, and if the +// destructor is trivial. +template <class ForwardIterator, class T> +inline void +__uninitialized_fill_aux(ForwardIterator first, ForwardIterator last, + const T& x, __true_type) +{ + fill(first, last, x); +} + +template <class ForwardIterator, class T> +void +__uninitialized_fill_aux(ForwardIterator first, ForwardIterator last, + const T& x, __false_type) +{ + ForwardIterator cur = first; +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + for ( ; cur != last; ++cur) + construct(&*cur, x); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy(first, cur); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ +} + +template <class ForwardIterator, class T, class T1> +inline void __uninitialized_fill(ForwardIterator first, ForwardIterator last, + const T& x, T1*) { + __uninitialized_fill_aux(first, last, x, + __type_traits<T1>::is_POD_type()); +} + +template <class ForwardIterator, class T> +inline void uninitialized_fill(ForwardIterator first, ForwardIterator last, + const T& x) { + __uninitialized_fill(first, last, x, value_type(first)); +} + +// Valid if copy construction is equivalent to assignment, and if the +// destructor is trivial. +template <class ForwardIterator, class Size, class T> +inline ForwardIterator +__uninitialized_fill_n_aux(ForwardIterator first, Size n, + const T& x, __true_type) { + return fill_n(first, n, x); +} + +template <class ForwardIterator, class Size, class T> +ForwardIterator +__uninitialized_fill_n_aux(ForwardIterator first, Size n, + const T& x, __false_type) { + ForwardIterator cur = first; +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + for ( ; n > 0; --n, ++cur) + construct(&*cur, x); + return cur; +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy(first, cur); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ +} + +template <class ForwardIterator, class Size, class T, class T1> +inline ForwardIterator __uninitialized_fill_n(ForwardIterator first, Size n, + const T& x, T1*) { + return __uninitialized_fill_n_aux(first, n, x, + __type_traits<T1>::is_POD_type()); +} + +template <class ForwardIterator, class Size, class T> +inline ForwardIterator uninitialized_fill_n(ForwardIterator first, Size n, + const T& x) { + return __uninitialized_fill_n(first, n, x, value_type(first)); +} + +// Copies [first1, last1) into [result, result + (last1 - first1)), and +// copies [first2, last2) into +// [result, result + (last1 - first1) + (last2 - first2)). + +template <class InputIterator1, class InputIterator2, class ForwardIterator> +inline ForwardIterator +__uninitialized_copy_copy(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + ForwardIterator result) { + ForwardIterator mid = uninitialized_copy(first1, last1, result); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + return uninitialized_copy(first2, last2, mid); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy(result, mid); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ +} + +// Fills [result, mid) with x, and copies [first, last) into +// [mid, mid + (last - first)). +template <class ForwardIterator, class T, class InputIterator> +inline ForwardIterator +__uninitialized_fill_copy(ForwardIterator result, ForwardIterator mid, + const T& x, + InputIterator first, InputIterator last) { + uninitialized_fill(result, mid, x); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + return uninitialized_copy(first, last, mid); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy(result, mid); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ +} + +// Copies [first1, last1) into [first2, first2 + (last1 - first1)), and +// fills [first2 + (last1 - first1), last2) with x. +template <class InputIterator, class ForwardIterator, class T> +inline void +__uninitialized_copy_fill(InputIterator first1, InputIterator last1, + ForwardIterator first2, ForwardIterator last2, + const T& x) { + ForwardIterator mid2 = uninitialized_copy(first1, last1, first2); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + uninitialized_fill(mid2, last2, x); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy(first2, mid2); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ +} + +#endif /* _SGI_STL_ALGOBASE_H */ diff --git a/libstdc++/stl/alloc.h b/libstdc++/stl/alloc.h new file mode 100644 index 0000000..917ce8f --- /dev/null +++ b/libstdc++/stl/alloc.h @@ -0,0 +1,674 @@ +/* + * Copyright (c) 1996-1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#ifndef __ALLOC_H +#define __ALLOC_H + +#include <stl_config.h> + +#ifdef __SUNPRO_CC +# define __PRIVATE public + // Extra access restrictions prevent us from really making some things + // private. +#else +# define __PRIVATE private +#endif + +#ifdef __STL_STATIC_TEMPLATE_MEMBER_BUG +# define __USE_MALLOC +#endif + + +// This implements some standard node allocators. These are +// NOT the same as the allocators in the C++ draft standard or in +// in the original STL. They do not encapsulate different pointer +// types; indeed we assume that there is only one pointer type. +// The allocation primitives are intended to allocate individual objects, +// not larger arenas as with the original STL allocators. + +#if 0 +# include <new> +# define __THROW_BAD_ALLOC throw bad_alloc +#elif !defined(__THROW_BAD_ALLOC) +# include <iostream.h> +# define __THROW_BAD_ALLOC cerr << "out of memory" << endl; exit(1) +#endif + +#ifndef __ALLOC +# define __ALLOC alloc +#endif +#ifdef __STL_WIN32THREADS +# include <windows.h> +// This must precede stl_config.h +#endif + +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#ifndef __RESTRICT +# define __RESTRICT +#endif + +#if !defined(_PTHREADS) && !defined(_NOTHREADS) \ + && !defined(__STL_SGI_THREADS) && !defined(__STL_WIN32THREADS) +# define _NOTHREADS +#endif + +# ifdef _PTHREADS + // POSIX Threads + // This is dubious, since this is likely to be a high contention + // lock. Performance may not be adequate. +# include <pthread.h> +# define __NODE_ALLOCATOR_LOCK \ + if (threads) pthread_mutex_lock(&__node_allocator_lock) +# define __NODE_ALLOCATOR_UNLOCK \ + if (threads) pthread_mutex_unlock(&__node_allocator_lock) +# define __NODE_ALLOCATOR_THREADS true +# define __VOLATILE volatile // Needed at -O3 on SGI +# endif +# ifdef __STL_WIN32THREADS + // The lock needs to be initialized by constructing an allocator + // objects of the right type. We do that here explicitly for alloc. +# define __NODE_ALLOCATOR_LOCK \ + EnterCriticalSection(&__node_allocator_lock) +# define __NODE_ALLOCATOR_UNLOCK \ + LeaveCriticalSection(&__node_allocator_lock) +# define __NODE_ALLOCATOR_THREADS true +# define __VOLATILE volatile // may not be needed +# endif /* WIN32THREADS */ +# ifdef __STL_SGI_THREADS + // This should work without threads, with sproc threads, or with + // pthreads. It is suboptimal in all cases. + // It is unlikely to even compile on nonSGI machines. +# include <malloc.h> +# define __NODE_ALLOCATOR_LOCK if (threads && __us_rsthread_malloc) \ + { __lock(&__node_allocator_lock); } +# define __NODE_ALLOCATOR_UNLOCK if (threads && __us_rsthread_malloc) \ + { __unlock(&__node_allocator_lock); } +# define __NODE_ALLOCATOR_THREADS true +# define __VOLATILE volatile // Needed at -O3 on SGI +# endif +# ifdef _NOTHREADS +// Thread-unsafe +# define __NODE_ALLOCATOR_LOCK +# define __NODE_ALLOCATOR_UNLOCK +# define __NODE_ALLOCATOR_THREADS false +# define __VOLATILE +# endif + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma set woff 1174 +#endif + +// Malloc-based allocator. Typically slower than default alloc below. +// Typically thread-safe and more storage efficient. +#ifdef __STL_STATIC_TEMPLATE_MEMBER_BUG +# ifdef __DECLARE_GLOBALS_HERE + void (* __malloc_alloc_oom_handler)() = 0; + // g++ 2.7.2 does not handle static template data members. +# else + extern void (* __malloc_alloc_oom_handler)(); +# endif +#endif + +template <int inst> +class __malloc_alloc_template { + +private: + +static void *oom_malloc(size_t); + +static void *oom_realloc(void *, size_t); + +#ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG + static void (* __malloc_alloc_oom_handler)(); +#endif + +public: + +static void * allocate(size_t n) +{ + void *result = malloc(n); + if (0 == result) result = oom_malloc(n); + return result; +} + +static void deallocate(void *p, size_t /* n */) +{ + free(p); +} + +static void * reallocate(void *p, size_t /* old_sz */, size_t new_sz) +{ + void * result = realloc(p, new_sz); + if (0 == result) result = oom_realloc(p, new_sz); + return result; +} + +static void (* set_malloc_handler(void (*f)()))() +{ + void (* old)() = __malloc_alloc_oom_handler; + __malloc_alloc_oom_handler = f; + return(old); +} + +}; + +// malloc_alloc out-of-memory handling + +#ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG +template <int inst> +void (* __malloc_alloc_template<inst>::__malloc_alloc_oom_handler)() = 0; +#endif + +template <int inst> +void * __malloc_alloc_template<inst>::oom_malloc(size_t n) +{ + void (* my_malloc_handler)(); + void *result; + + for (;;) { + my_malloc_handler = __malloc_alloc_oom_handler; + if (0 == my_malloc_handler) { __THROW_BAD_ALLOC; } + (*my_malloc_handler)(); + result = malloc(n); + if (result) return(result); + } +} + +template <int inst> +void * __malloc_alloc_template<inst>::oom_realloc(void *p, size_t n) +{ + void (* my_malloc_handler)(); + void *result; + + for (;;) { + my_malloc_handler = __malloc_alloc_oom_handler; + if (0 == my_malloc_handler) { __THROW_BAD_ALLOC; } + (*my_malloc_handler)(); + result = realloc(p, n); + if (result) return(result); + } +} + +typedef __malloc_alloc_template<0> malloc_alloc; + +template<class T, class Alloc> +class simple_alloc { + +public: + static T *allocate(size_t n) + { return 0 == n? 0 : (T*) Alloc::allocate(n * sizeof (T)); } + static T *allocate(void) + { return (T*) Alloc::allocate(sizeof (T)); } + static void deallocate(T *p, size_t n) + { if (0 != n) Alloc::deallocate(p, n * sizeof (T)); } + static void deallocate(T *p) + { Alloc::deallocate(p, sizeof (T)); } +}; + +// Allocator adaptor to check size arguments for debugging. +// Reports errors using assert. Checking can be disabled with +// NDEBUG, but it's far better to just use the underlying allocator +// instead when no checking is desired. +// There is some evidence that this can confuse Purify. +template <class Alloc> +class debug_alloc { + +private: + +enum {extra = 8}; // Size of space used to store size. Note + // that this must be large enough to preserve + // alignment. + +public: + +static void * allocate(size_t n) +{ + char *result = (char *)Alloc::allocate(n + extra); + *(size_t *)result = n; + return result + extra; +} + +static void deallocate(void *p, size_t n) +{ + char * real_p = (char *)p - extra; + assert(*(size_t *)real_p == n); + Alloc::deallocate(real_p, n + extra); +} + +static void * reallocate(void *p, size_t old_sz, size_t new_sz) +{ + char * real_p = (char *)p - extra; + assert(*(size_t *)real_p == old_sz); + char * result = (char *) + Alloc::reallocate(real_p, old_sz + extra, new_sz + extra); + *(size_t *)result = new_sz; + return result + extra; +} + + +}; + + +# ifdef __USE_MALLOC + +typedef malloc_alloc alloc; +typedef malloc_alloc single_client_alloc; + +# else + + +// Default node allocator. +// With a reasonable compiler, this should be roughly as fast as the +// original STL class-specific allocators, but with less fragmentation. +// Default_alloc_template parameters are experimental and MAY +// DISAPPEAR in the future. Clients should just use alloc for now. +// +// Important implementation properties: +// 1. If the client request an object of size > __MAX_BYTES, the resulting +// object will be obtained directly from malloc. +// 2. In all other cases, we allocate an object of size exactly +// ROUND_UP(requested_size). Thus the client has enough size +// information that we can return the object to the proper free list +// without permanently losing part of the object. +// + +// The first template parameter specifies whether more than one thread +// may use this allocator. It is safe to allocate an object from +// one instance of a default_alloc and deallocate it with another +// one. This effectively transfers its ownership to the second one. +// This may have undesirable effects on reference locality. +// The second parameter is unreferenced and serves only to allow the +// creation of multiple default_alloc instances. +// Node that containers built on different allocator instances have +// different types, limiting the utility of this approach. +#ifdef __SUNPRO_CC +// breaks if we make these template class members: + enum {__ALIGN = 8}; + enum {__MAX_BYTES = 128}; + enum {__NFREELISTS = __MAX_BYTES/__ALIGN}; +#endif + +template <bool threads, int inst> +class __default_alloc_template { + +private: + // Really we should use static const int x = N + // instead of enum { x = N }, but few compilers accept the former. +# ifndef __SUNPRO_CC + enum {__ALIGN = 8}; + enum {__MAX_BYTES = 128}; + enum {__NFREELISTS = __MAX_BYTES/__ALIGN}; +# endif + static size_t ROUND_UP(size_t bytes) { + return (((bytes) + __ALIGN-1) & ~(__ALIGN - 1)); + } +__PRIVATE: + union obj { + union obj * free_list_link; + char client_data[1]; /* The client sees this. */ + }; +private: +# ifdef __SUNPRO_CC + static obj * __VOLATILE free_list[]; + // Specifying a size results in duplicate def for 4.1 +# else + static obj * __VOLATILE free_list[__NFREELISTS]; +# endif + static size_t FREELIST_INDEX(size_t bytes) { + return (((bytes) + __ALIGN-1)/__ALIGN - 1); + } + + // Returns an object of size n, and optionally adds to size n free list. + static void *refill(size_t n); + // Allocates a chunk for nobjs of size size. nobjs may be reduced + // if it is inconvenient to allocate the requested number. + static char *chunk_alloc(size_t size, int &nobjs); + + // Chunk allocation state. + static char *start_free; + static char *end_free; + static size_t heap_size; + +# ifdef __STL_SGI_THREADS + static volatile unsigned long __node_allocator_lock; + static void __lock(volatile unsigned long *); + static inline void __unlock(volatile unsigned long *); +# endif + +# ifdef _PTHREADS + static pthread_mutex_t __node_allocator_lock; +# endif + +# ifdef __STL_WIN32THREADS + static CRITICAL_SECTION __node_allocator_lock; + static bool __node_allocator_lock_initialized; + + public: + __default_alloc_template() { + // This assumes the first constructor is called before threads + // are started. + if (!__node_allocator_lock_initialized) { + InitializeCriticalSection(&__node_allocator_lock); + __node_allocator_lock_initialized = true; + } + } + private: +# endif + + class lock { + public: + lock() { __NODE_ALLOCATOR_LOCK; } + ~lock() { __NODE_ALLOCATOR_UNLOCK; } + }; + friend class lock; + +public: + + /* n must be > 0 */ + static void * allocate(size_t n) + { + obj * __VOLATILE * my_free_list; + obj * __RESTRICT result; + + if (n > __MAX_BYTES) { + return(malloc_alloc::allocate(n)); + } + my_free_list = free_list + FREELIST_INDEX(n); + // Acquire the lock here with a constructor call. + // This ensures that it is released in exit or during stack + // unwinding. + /*REFERENCED*/ + lock lock_instance; + result = *my_free_list; + if (result == 0) { + void *r = refill(ROUND_UP(n)); + return r; + } + *my_free_list = result -> free_list_link; + return (result); + }; + + /* p may not be 0 */ + static void deallocate(void *p, size_t n) + { + obj *q = (obj *)p; + obj * __VOLATILE * my_free_list; + + if (n > __MAX_BYTES) { + malloc_alloc::deallocate(p, n); + return; + } + my_free_list = free_list + FREELIST_INDEX(n); + // acquire lock + /*REFERENCED*/ + lock lock_instance; + q -> free_list_link = *my_free_list; + *my_free_list = q; + // lock is released here + } + + static void * reallocate(void *p, size_t old_sz, size_t new_sz); + +} ; + +typedef __default_alloc_template<__NODE_ALLOCATOR_THREADS, 0> alloc; +typedef __default_alloc_template<false, 0> single_client_alloc; + + + +/* We allocate memory in large chunks in order to avoid fragmenting */ +/* the malloc heap too much. */ +/* We assume that size is properly aligned. */ +/* We hold the allocation lock. */ +template <bool threads, int inst> +char* +__default_alloc_template<threads, inst>::chunk_alloc(size_t size, int& nobjs) +{ + char * result; + size_t total_bytes = size * nobjs; + size_t bytes_left = end_free - start_free; + + if (bytes_left >= total_bytes) { + result = start_free; + start_free += total_bytes; + return(result); + } else if (bytes_left >= size) { + nobjs = bytes_left/size; + total_bytes = size * nobjs; + result = start_free; + start_free += total_bytes; + return(result); + } else { + size_t bytes_to_get = 2 * total_bytes + ROUND_UP(heap_size >> 4); + // Try to make use of the left-over piece. + if (bytes_left > 0) { + obj * __VOLATILE * my_free_list = + free_list + FREELIST_INDEX(bytes_left); + + ((obj *)start_free) -> free_list_link = *my_free_list; + *my_free_list = (obj *)start_free; + } + start_free = (char *)malloc(bytes_to_get); + if (0 == start_free) { + int i; + obj * __VOLATILE * my_free_list, *p; + // Try to make do with what we have. That can't + // hurt. We do not try smaller requests, since that tends + // to result in disaster on multi-process machines. + for (i = size; i <= __MAX_BYTES; i += __ALIGN) { + my_free_list = free_list + FREELIST_INDEX(i); + p = *my_free_list; + if (0 != p) { + *my_free_list = p -> free_list_link; + start_free = (char *)p; + end_free = start_free + i; + return(chunk_alloc(size, nobjs)); + // Any leftover piece will eventually make it to the + // right free list. + } + } + start_free = (char *)malloc_alloc::allocate(bytes_to_get); + // This should either throw an + // exception or remedy the situation. Thus we assume it + // succeeded. + } + heap_size += bytes_to_get; + end_free = start_free + bytes_to_get; + return(chunk_alloc(size, nobjs)); + } +} + + +/* Returns an object of size n, and optionally adds to size n free list.*/ +/* We assume that n is properly aligned. */ +/* We hold the allocation lock. */ +template <bool threads, int inst> +void* __default_alloc_template<threads, inst>::refill(size_t n) +{ + int nobjs = 20; + char * chunk = chunk_alloc(n, nobjs); + obj * __VOLATILE * my_free_list; + obj * result; + obj * current_obj, * next_obj; + int i; + + if (1 == nobjs) return(chunk); + my_free_list = free_list + FREELIST_INDEX(n); + + /* Build free list in chunk */ + result = (obj *)chunk; + *my_free_list = next_obj = (obj *)(chunk + n); + for (i = 1; ; i++) { + current_obj = next_obj; + next_obj = (obj *)((char *)next_obj + n); + if (nobjs - 1 == i) { + current_obj -> free_list_link = 0; + break; + } else { + current_obj -> free_list_link = next_obj; + } + } + return(result); +} + +template <bool threads, int inst> +void* +__default_alloc_template<threads, inst>::reallocate(void *p, + size_t old_sz, + size_t new_sz) +{ + void * result; + size_t copy_sz; + + if (old_sz > __MAX_BYTES && new_sz > __MAX_BYTES) { + return(realloc(p, new_sz)); + } + if (ROUND_UP(old_sz) == ROUND_UP(new_sz)) return(p); + result = allocate(new_sz); + copy_sz = new_sz > old_sz? old_sz : new_sz; + memcpy(result, p, copy_sz); + deallocate(p, old_sz); + return(result); +} + +#ifdef _PTHREADS + template <bool threads, int inst> + pthread_mutex_t + __default_alloc_template<threads, inst>::__node_allocator_lock + = PTHREAD_MUTEX_INITIALIZER; +#endif + +#ifdef __STL_WIN32THREADS + template <bool threads, int inst> CRITICAL_SECTION + __default_alloc_template<threads, inst>::__node_allocator_lock; + + template <bool threads, int inst> bool + __default_alloc_template<threads, inst>::__node_allocator_lock_initialized + = false; +#endif + +#ifdef __STL_SGI_THREADS +#include <mutex.h> +#include <time.h> +// Somewhat generic lock implementations. We need only test-and-set +// and some way to sleep. These should work with both SGI pthreads +// and sproc threads. They may be useful on other systems. +template <bool threads, int inst> +volatile unsigned long +__default_alloc_template<threads, inst>::__node_allocator_lock = 0; + +#if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) || defined(__GNUC__) +# define __test_and_set(l,v) test_and_set(l,v) +#endif + +template <bool threads, int inst> +void +__default_alloc_template<threads, inst>::__lock(volatile unsigned long *lock) +{ + const unsigned low_spin_max = 30; // spin cycles if we suspect uniprocessor + const unsigned high_spin_max = 1000; // spin cycles for multiprocessor + static unsigned spin_max = low_spin_max; + unsigned my_spin_max; + static unsigned last_spins = 0; + unsigned my_last_spins; + static struct timespec ts = {0, 1000}; + unsigned junk; +# define __ALLOC_PAUSE junk *= junk; junk *= junk; junk *= junk; junk *= junk + int i; + + if (!__test_and_set((unsigned long *)lock, 1)) { + return; + } + my_spin_max = spin_max; + my_last_spins = last_spins; + for (i = 0; i < my_spin_max; i++) { + if (i < my_last_spins/2 || *lock) { + __ALLOC_PAUSE; + continue; + } + if (!__test_and_set((unsigned long *)lock, 1)) { + // got it! + // Spinning worked. Thus we're probably not being scheduled + // against the other process with which we were contending. + // Thus it makes sense to spin longer the next time. + last_spins = i; + spin_max = high_spin_max; + return; + } + } + // We are probably being scheduled against the other process. Sleep. + spin_max = low_spin_max; + for (;;) { + if (!__test_and_set((unsigned long *)lock, 1)) { + return; + } + nanosleep(&ts, 0); + } +} + +template <bool threads, int inst> +inline void +__default_alloc_template<threads, inst>::__unlock(volatile unsigned long *lock) +{ +# if defined(__GNUC__) && __mips >= 3 + asm("sync"); + *lock = 0; +# elif __mips >= 3 && (defined (_ABIN32) || defined(_ABI64)) + __lock_release(lock); +# else + *lock = 0; + // This is not sufficient on many multiprocessors, since + // writes to protected variables and the lock may be reordered. +# endif +} +#endif + +template <bool threads, int inst> +char *__default_alloc_template<threads, inst>::start_free = 0; + +template <bool threads, int inst> +char *__default_alloc_template<threads, inst>::end_free = 0; + +template <bool threads, int inst> +size_t __default_alloc_template<threads, inst>::heap_size = 0; + +template <bool threads, int inst> +__default_alloc_template<threads, inst>::obj * __VOLATILE +__default_alloc_template<threads, inst> ::free_list[ +# ifdef __SUNPRO_CC + __NFREELISTS +# else + __default_alloc_template<threads, inst>::__NFREELISTS +# endif +] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; +// The 16 zeros are necessary to make version 4.1 of the SunPro +// compiler happy. Otherwise it appears to allocate too little +// space for the array. + +# ifdef __STL_WIN32THREADS + // Create one to get critical section initialized. + // We do this onece per file, but only the first constructor + // does anything. + static alloc __node_allocator_dummy_instance; +# endif + +#endif /* ! __USE_MALLOC */ + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma reset woff 1174 +#endif + +#endif /* __NODE_ALLOC_H */ diff --git a/libstdc++/stl/bvector.h b/libstdc++/stl/bvector.h new file mode 100644 index 0000000..2787879 --- /dev/null +++ b/libstdc++/stl/bvector.h @@ -0,0 +1,585 @@ +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +// vector<bool> is replaced by bit_vector at present because partial +// specialization is not yet implemented. + +#ifndef __SGI_STL_BVECTOR_H +#define __SGI_STL_BVECTOR_H + +#include <stddef.h> +#include <algobase.h> +#include <alloc.h> + + +#define __WORD_BIT (int(CHAR_BIT*sizeof(unsigned int))) + +class bit_vector { +public: + typedef bool value_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + class iterator; + class const_iterator; + + class reference { + friend class iterator; + friend class const_iterator; + protected: + unsigned int* p; + unsigned int mask; + reference(unsigned int* x, unsigned int y) : p(x), mask(y) {} + public: + reference() : p(0), mask(0) {} + operator bool() const { return !(!(*p & mask)); } + reference& operator=(bool x) { + if (x) + *p |= mask; + else + *p &= ~mask; + return *this; + } + reference& operator=(const reference& x) { return *this = bool(x); } + bool operator==(const reference& x) const { + return bool(*this) == bool(x); + } + bool operator<(const reference& x) const { + return bool(*this) < bool(x); + } + void flip() { *p ^= mask; } + }; + + typedef bool const_reference; + + typedef reference bit_reference; + typedef const_reference bit_const_reference; + + class iterator : public random_access_iterator<bool, difference_type> { + friend class bit_vector; + friend class const_iterator; + public: + typedef bit_reference reference; + protected: + unsigned int* p; + unsigned int offset; + void bump_up() { + if (offset++ == __WORD_BIT - 1) { + offset = 0; + ++p; + } + } + void bump_down() { + if (offset-- == 0) { + offset = __WORD_BIT - 1; + --p; + } + } + public: + iterator() : p(0), offset(0) {} + iterator(unsigned int* x, unsigned int y) : p(x), offset(y) {} + reference operator*() const { return reference(p, 1U << offset); } + iterator& operator++() { + bump_up(); + return *this; + } + iterator operator++(int) { + iterator tmp = *this; + bump_up(); + return tmp; + } + iterator& operator--() { + bump_down(); + return *this; + } + iterator operator--(int) { + iterator tmp = *this; + bump_down(); + return tmp; + } + iterator& operator+=(difference_type i) { + difference_type n = i + offset; + p += n / __WORD_BIT; + n = n % __WORD_BIT; + if (n < 0) { + offset = n + __WORD_BIT; + --p; + } else + offset = n; + return *this; + } + iterator& operator-=(difference_type i) { + *this += -i; + return *this; + } + iterator operator+(difference_type i) const { + iterator tmp = *this; + return tmp += i; + } + iterator operator-(difference_type i) const { + iterator tmp = *this; + return tmp -= i; + } + difference_type operator-(iterator x) const { + return __WORD_BIT * (p - x.p) + offset - x.offset; + } + reference operator[](difference_type i) { return *(*this + i); } + bool operator==(const iterator& x) const { + return p == x.p && offset == x.offset; + } + bool operator!=(const iterator& x) const { + return p != x.p || offset != x.offset; + } + bool operator<(iterator x) const { + return p < x.p || (p == x.p && offset < x.offset); + } + }; + + class const_iterator : public random_access_iterator<bool, difference_type> + { + friend class bit_vector; + public: + typedef bit_const_reference reference; + protected: + unsigned int* p; + unsigned int offset; + void bump_up() { + if (offset++ == __WORD_BIT - 1) { + offset = 0; + ++p; + } + } + void bump_down() { + if (offset-- == 0) { + offset = __WORD_BIT - 1; + --p; + } + } + public: + const_iterator() : p(0), offset(0) {} + const_iterator(unsigned int* x, unsigned int y) : p(x), offset(y) {} + const_iterator(const iterator& x) : p(x.p), offset(x.offset) {} + const_reference operator*() const { + return bit_vector::reference(p, 1U << offset); + } + const_iterator& operator++() { + bump_up(); + return *this; + } + const_iterator operator++(int) { + const_iterator tmp = *this; + bump_up(); + return tmp; + } + const_iterator& operator--() { + bump_down(); + return *this; + } + const_iterator operator--(int) { + const_iterator tmp = *this; + bump_down(); + return tmp; + } + const_iterator& operator+=(difference_type i) { + difference_type n = i + offset; + p += n / __WORD_BIT; + n = n % __WORD_BIT; + if (n < 0) { + offset = n + __WORD_BIT; + --p; + } else + offset = n; + return *this; + } + const_iterator& operator-=(difference_type i) { + *this += -i; + return *this; + } + const_iterator operator+(difference_type i) const { + const_iterator tmp = *this; + return tmp += i; + } + const_iterator operator-(difference_type i) const { + const_iterator tmp = *this; + return tmp -= i; + } + difference_type operator-(const_iterator x) const { + return __WORD_BIT * (p - x.p) + offset - x.offset; + } + const_reference operator[](difference_type i) { + return *(*this + i); + } + bool operator==(const const_iterator& x) const { + return p == x.p && offset == x.offset; + } + bool operator!=(const const_iterator& x) const { + return p != x.p || offset != x.offset; + } + bool operator<(const_iterator x) const { + return p < x.p || (p == x.p && offset < x.offset); + } + }; + + typedef reverse_iterator<const_iterator, value_type, const_reference, + difference_type> const_reverse_iterator; + typedef reverse_iterator<iterator, value_type, reference, difference_type> + reverse_iterator; + +protected: + typedef simple_alloc<unsigned int, alloc> data_allocator; + iterator start; + iterator finish; + unsigned int* end_of_storage; + unsigned int* bit_alloc(size_type n) { + return data_allocator::allocate((n + __WORD_BIT - 1)/__WORD_BIT); + } + void deallocate() { + if (start.p) + data_allocator::deallocate(start.p, end_of_storage - start.p); + } + void initialize(size_type n) { + unsigned int* q = bit_alloc(n); + end_of_storage = q + (n + __WORD_BIT - 1)/__WORD_BIT; + start = iterator(q, 0); + finish = start + n; + } + void insert_aux(iterator position, bool x) { + if (finish.p != end_of_storage) { + copy_backward(position, finish, finish + 1); + *position = x; + ++finish; + } else { + size_type len = size() ? 2 * size() : __WORD_BIT; + unsigned int* q = bit_alloc(len); + iterator i = copy(begin(), position, iterator(q, 0)); + *i++ = x; + finish = copy(position, end(), i); + deallocate(); + end_of_storage = q + (len + __WORD_BIT - 1)/__WORD_BIT; + start = iterator(q, 0); + } + } + +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + void initialize_range(InputIterator first, InputIterator last, + input_iterator_tag) { + start = iterator(); + finish = iterator(); + end_of_storage = 0; + for ( ; first != last; ++first) + push_back(*first); + } + + template <class ForwardIterator> + void initialize_range(ForwardIterator first, ForwardIterator last, + forward_iterator_tag) { + size_type n = 0; + distance(first, last, n); + initialize(n); + copy(first, last, start); + } + + template <class BidirectionalIterator> + void initialize_range(BidirectionalIterator first, + BidirectionalIterator last, + bidirectional_iterator_tag) { + initialize_range(first, last, forward_iterator_tag()); + } + + template <class RandomAccessIterator> + void initialize_range(RandomAccessIterator first, + RandomAccessIterator last, + random_access_iterator_tag) { + initialize_range(first, last, forward_iterator_tag()); + } + + template <class InputIterator> + void insert_range(iterator pos, + InputIterator first, InputIterator last, + input_iterator_tag) { + for ( ; first != last; ++first) { + pos = insert(pos, *first); + ++pos; + } + } + + template <class ForwardIterator> + void insert_range(iterator position, + ForwardIterator first, ForwardIterator last, + forward_iterator_tag) { + if (first != last) { + size_type n = 0; + distance(first, last, n); + if (capacity() - size() >= n) { + copy_backward(position, end(), finish + n); + copy(first, last, position); + finish += n; + } + else { + size_type len = size() + max(size(), n); + unsigned int* q = bit_alloc(len); + iterator i = copy(begin(), position, iterator(q, 0)); + i = copy(first, last, i); + finish = copy(position, end(), i); + deallocate(); + end_of_storage = q + (len + __WORD_BIT - 1)/__WORD_BIT; + start = iterator(q, 0); + } + } + } + + template <class BidirectionalIterator> + void insert_range(iterator pos, + BidirectionalIterator first, BidirectionalIterator last, + bidirectional_iterator_tag) { + insert_range(pos, first, last, forward_iterator_tag()); + } + + template <class RandomAccessIterator> + void insert_range(iterator pos, + RandomAccessIterator first, RandomAccessIterator last, + random_access_iterator_tag) { + insert_range(pos, first, last, forward_iterator_tag()); + } + +#endif /* __STL_MEMBER_TEMPLATES */ + + typedef bit_vector self; +public: + iterator begin() { return start; } + const_iterator begin() const { return start; } + iterator end() { return finish; } + const_iterator end() const { return finish; } + + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + + size_type size() const { return size_type(end() - begin()); } + size_type max_size() const { return size_type(-1); } + size_type capacity() const { + return size_type(const_iterator(end_of_storage, 0) - begin()); + } + bool empty() const { return begin() == end(); } + reference operator[](size_type n) { return *(begin() + n); } + const_reference operator[](size_type n) const { return *(begin() + n); } + bit_vector() : start(iterator()), finish(iterator()), end_of_storage(0) {} + bit_vector(size_type n, bool value) { + initialize(n); + fill(start.p, end_of_storage, value ? ~0 : 0); + } + bit_vector(int n, bool value) { + initialize(n); + fill(start.p, end_of_storage, value ? ~0 : 0); + } + bit_vector(long n, bool value) { + initialize(n); + fill(start.p, end_of_storage, value ? ~0 : 0); + } + explicit bit_vector(size_type n) { + initialize(n); + fill(start.p, end_of_storage, 0); + } + bit_vector(const self& x) { + initialize(x.size()); + copy(x.begin(), x.end(), start); + } + +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + bit_vector(InputIterator first, InputIterator last) { + initialize_range(first, last, iterator_category(first)); + } +#else /* __STL_MEMBER_TEMPLATES */ + bit_vector(const_iterator first, const_iterator last) { + size_type n = 0; + distance(first, last, n); + initialize(n); + copy(first, last, start); + } + bit_vector(const bool* first, const bool* last) { + size_type n = 0; + distance(first, last, n); + initialize(n); + copy(first, last, start); + } +#endif /* __STL_MEMBER_TEMPLATES */ + + ~bit_vector() { deallocate(); } + self& operator=(const self& x) { + if (&x == this) return *this; + if (x.size() > capacity()) { + deallocate(); + initialize(x.size()); + } + copy(x.begin(), x.end(), begin()); + finish = begin() + x.size(); + return *this; + } + void reserve(size_type n) { + if (capacity() < n) { + unsigned int* q = bit_alloc(n); + finish = copy(begin(), end(), iterator(q, 0)); + deallocate(); + start = iterator(q, 0); + end_of_storage = q + (n + __WORD_BIT - 1)/__WORD_BIT; + } + } + reference front() { return *begin(); } + const_reference front() const { return *begin(); } + reference back() { return *(end() - 1); } + const_reference back() const { return *(end() - 1); } + void push_back(bool x) { + if (finish.p != end_of_storage) + *finish++ = x; + else + insert_aux(end(), x); + } + void swap(bit_vector& x) { + ::swap(start, x.start); + ::swap(finish, x.finish); + ::swap(end_of_storage, x.end_of_storage); + } + iterator insert(iterator position, bool x = bool()) { + size_type n = position - begin(); + if (finish.p != end_of_storage && position == end()) + *finish++ = x; + else + insert_aux(position, x); + return begin() + n; + } + +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> void insert(iterator position, + InputIterator first, + InputIterator last) { + insert_range(position, first, last, iterator_category(first)); + } +#else /* __STL_MEMBER_TEMPLATES */ + void insert(iterator position, const_iterator first, + const_iterator last) { + if (first == last) return; + size_type n = 0; + distance(first, last, n); + if (capacity() - size() >= n) { + copy_backward(position, end(), finish + n); + copy(first, last, position); + finish += n; + } else { + size_type len = size() + max(size(), n); + unsigned int* q = bit_alloc(len); + iterator i = copy(begin(), position, iterator(q, 0)); + i = copy(first, last, i); + finish = copy(position, end(), i); + deallocate(); + end_of_storage = q + (len + __WORD_BIT - 1)/__WORD_BIT; + start = iterator(q, 0); + } + } + + void insert(iterator position, const bool* first, const bool* last) { + if (first == last) return; + size_type n = 0; + distance(first, last, n); + if (capacity() - size() >= n) { + copy_backward(position, end(), finish + n); + copy(first, last, position); + finish += n; + } else { + size_type len = size() + max(size(), n); + unsigned int* q = bit_alloc(len); + iterator i = copy(begin(), position, iterator(q, 0)); + i = copy(first, last, i); + finish = copy(position, end(), i); + deallocate(); + end_of_storage = q + (len + __WORD_BIT - 1)/__WORD_BIT; + start = iterator(q, 0); + } + } +#endif /* __STL_MEMBER_TEMPLATES */ + + void insert(iterator position, size_type n, bool x) { + if (n == 0) return; + if (capacity() - size() >= n) { + copy_backward(position, end(), finish + n); + fill(position, position + n, x); + finish += n; + } else { + size_type len = size() + max(size(), n); + unsigned int* q = bit_alloc(len); + iterator i = copy(begin(), position, iterator(q, 0)); + fill_n(i, n, x); + finish = copy(position, end(), i + n); + deallocate(); + end_of_storage = q + (len + __WORD_BIT - 1)/__WORD_BIT; + start = iterator(q, 0); + } + } + + void insert(iterator pos, int n, bool x) { insert(pos, (size_type)n, x); } + void insert(iterator pos, long n, bool x) { insert(pos, (size_type)n, x); } + + void pop_back() { --finish; } + void erase(iterator position) { + if (position + 1 != end()) + copy(position + 1, end(), position); + --finish; + } + void erase(iterator first, iterator last) { + finish = copy(last, end(), first); + } + void resize(size_type new_size, bool x = bool()) { + if (new_size < size()) + erase(begin() + new_size, end()); + else + insert(end(), new_size - size(), x); + } + void clear() { erase(begin(), end()); } +}; + +inline bool operator==(const bit_vector& x, const bit_vector& y) { + return x.size() == y.size() && equal(x.begin(), x.end(), y.begin()); +} + +inline bool operator<(const bit_vector& x, const bit_vector& y) { + return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); +} + +inline void swap(bit_vector::reference x, bit_vector::reference y) { + bool tmp = x; + x = y; + y = tmp; +} + +#undef __WORD_BIT + +#endif /* __SGI_STL_BVECTOR_H */ diff --git a/libstdc++/stl/defalloc.h b/libstdc++/stl/defalloc.h new file mode 100644 index 0000000..e7d24d3 --- /dev/null +++ b/libstdc++/stl/defalloc.h @@ -0,0 +1,87 @@ +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ +// +// Inclusion of this file is DEPRECATED. +// This is the original HP default allocator. +// DO NOT USE THIS FILE unless you have an old container implementation +// that requires an allocator with the HP-style interface. +// SGI STL uses a different allocator interface. +// SGI-style allocators are not parametrized with respect to +// the object type; they traffic in void * pointers. +// This file is not included by any other SGI STL header. +// + +#ifndef DEFALLOC_H +#define DEFALLOC_H + +#include <new.h> +#include <stddef.h> +#include <stdlib.h> +#include <limits.h> +#include <iostream.h> +#include <algobase.h> + + +template <class T> +inline T* allocate(ptrdiff_t size, T*) { + set_new_handler(0); + T* tmp = (T*)(::operator new((size_t)(size * sizeof(T)))); + if (tmp == 0) { + cerr << "out of memory" << endl; + exit(1); + } + return tmp; +} + + +template <class T> +inline void deallocate(T* buffer) { + ::operator delete(buffer); +} + +template <class T> +class allocator { +public: + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + pointer allocate(size_type n) { + return ::allocate((difference_type)n, (pointer)0); + } + void deallocate(pointer p) { ::deallocate(p); } + pointer address(reference x) { return (pointer)&x; } + const_pointer const_address(const_reference x) { + return (const_pointer)&x; + } + size_type init_page_size() { + return max(size_type(1), size_type(4096/sizeof(T))); + } + size_type max_size() const { + return max(size_type(1), size_type(UINT_MAX/sizeof(T))); + } +}; + +class allocator<void> { +public: + typedef void* pointer; +}; + + + +#endif diff --git a/libstdc++/stl/deque.h b/libstdc++/stl/deque.h new file mode 100644 index 0000000..6685abf --- /dev/null +++ b/libstdc++/stl/deque.h @@ -0,0 +1,1452 @@ +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#ifndef __SGI_STL_DEQUE_H +#define __SGI_STL_DEQUE_H + +/* Class invariants: + * For any nonsingular iterator i: + * i.node is the address of an element in the map array. The + * contents of i.node is a pointer to the beginning of a node. + * i.first == *(i.node) + * i.last == i.first + node_size + * i.cur is a pointer in the range [i.first, i.last). NOTE: + * the implication of this is that i.cur is always a dereferenceable + * pointer, even if i is a past-the-end iterator. + * Start and Finish are always nonsingular iterators. NOTE: this means + * that an empty deque must have one node, and that a deque + * with N elements, where N is the buffer size, must have two nodes. + * For every node other than start.node and finish.node, every element + * in the node is an initialized object. If start.node == finish.node, + * then [start.cur, finish.cur) are initialized objects, and + * the elements outside that range are uninitialized storage. Otherwise, + * [start.cur, start.last) and [finish.first, finish.cur) are initialized + * objects, and [start.first, start.cur) and [finish.cur, finish.last) + * are uninitialized storage. + * [map, map + map_size) is a valid, non-empty range. + * [start.node, finish.node] is a valid range contained within + * [map, map + map_size). + * A pointer in the range [map, map + map_size) points to an allocated + * node if and only if the pointer is in the range [start.node, finish.node]. + */ + + +/* + * In previous versions of deque, node_size was fixed by the + * implementation. In this version, however, users can select + * the node size. Deque has three template parameters; the third, + * a number of type size_t, is the number of elements per node. + * If the third template parameter is 0 (which is the default), + * then deque will use a default node size. + * + * The only reason for using an alternate node size is if your application + * requires a different performance tradeoff than the default. If, + * for example, your program contains many deques each of which contains + * only a few elements, then you might want to save memory (possibly + * by sacrificing some speed) by using smaller nodes. + * + * Unfortunately, some compilers have trouble with non-type template + * parameters; stl_config.h defines __STL_NON_TYPE_TMPL_PARAM_BUG if + * that is the case. If your compiler is one of them, then you will + * not be able to use alternate node sizes; you will have to use the + * default value. + */ + +#include <stddef.h> +#include <algobase.h> +#include <alloc.h> + +// Note: this function is simply a kludge to work around several compilers' +// bugs in handling constant expressions. +inline size_t __deque_buf_size(size_t n, size_t sz) +{ + return n != 0 ? n : (sz < 512 ? size_t(512 / sz) : size_t(1)); +} + +#ifndef __STL_NON_TYPE_TMPL_PARAM_BUG +template <class T, class Ref, size_t BufSiz> +struct __deque_iterator { + typedef __deque_iterator<T, T&, BufSiz> iterator; + typedef __deque_iterator<T, const T&, BufSiz> const_iterator; + static size_t buffer_size() {return __deque_buf_size(BufSiz, sizeof(T)); } +#else /* __STL_NON_TYPE_TMPL_PARAM_BUG */ +template <class T, class Ref> +struct __deque_iterator { + typedef __deque_iterator<T, T&> iterator; + typedef __deque_iterator<T, const T&> const_iterator; + static size_t buffer_size() {return __deque_buf_size(0, sizeof(T)); } +#endif + + typedef random_access_iterator_tag iterator_category; + typedef T value_type; + typedef value_type* pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef pointer* map_pointer; + + typedef __deque_iterator self; + + pointer cur; + pointer first; + pointer last; + map_pointer node; + + __deque_iterator(pointer x, map_pointer y) + : cur(x), first(*y), last(*y + buffer_size()), node(y) {} + __deque_iterator() : cur(0), first(0), last(0), node(0) {} + __deque_iterator(const iterator& x) + : cur(x.cur), first(x.first), last(x.last), node(x.node) {} + + Ref operator*() const { return *cur; } + + difference_type operator-(const self& x) const { + return buffer_size() * (node - x.node - 1) + + (cur - first) + (x.last - x.cur); + } + + self& operator++() { + ++cur; + if (cur == last) { + set_node(node + 1); + cur = first; + } + return *this; + } + self operator++(int) { + self tmp = *this; + ++*this; + return tmp; + } + + self& operator--() { + if (cur == first) { + set_node(node - 1); + cur = last; + } + --cur; + return *this; + } + self operator--(int) { + self tmp = *this; + --*this; + return tmp; + } + + self& operator+=(difference_type n) { + difference_type offset = n + (cur - first); + if (offset >= 0 && offset < buffer_size()) + cur += n; + else { + difference_type node_offset = + offset > 0 ? offset / buffer_size() + : -difference_type((-offset - 1) / buffer_size()) - 1; + set_node(node + node_offset); + cur = first + (offset - node_offset * buffer_size()); + } + return *this; + } + + self operator+(difference_type n) const { + self tmp = *this; + return tmp += n; + } + + self& operator-=(difference_type n) { return *this += -n; } + + self operator-(difference_type n) const { + self tmp = *this; + return tmp -= n; + } + + Ref operator[](difference_type n) const { return *(*this + n); } + + bool operator==(const self& x) const { return cur == x.cur; } + bool operator!=(const self& x) const { return !(*this == x); } + bool operator<(const self& x) const { + return (node == x.node) ? (cur < x.cur) : (node < x.node); + } + + void set_node(map_pointer new_node) { + node = new_node; + first = *new_node; + last = first + buffer_size(); + } +}; + +#ifndef __STL_NON_TYPE_TMPL_PARAM_BUG + +template <class T, class Ref, size_t BufSiz> +inline random_access_iterator_tag +iterator_category(const __deque_iterator<T, Ref, BufSiz>&) { + return random_access_iterator_tag(); +} + +template <class T, class Ref, size_t BufSiz> +inline T* value_type(const __deque_iterator<T, Ref, BufSiz>&) { return 0; } + +template <class T, class Ref, size_t BufSiz> +inline ptrdiff_t* distance_type(const __deque_iterator<T, Ref, BufSiz>&) { + return 0; +} + +#else /* __STL_NON_TYPE_TMPL_PARAM_BUG */ + +template <class T, class Ref> +inline random_access_iterator_tag +iterator_category(const __deque_iterator<T, Ref>&) { + return random_access_iterator_tag(); +} + +template <class T, class Ref> +inline T* value_type(const __deque_iterator<T, Ref>&) { return 0; } + +template <class T, class Ref> +inline ptrdiff_t* distance_type(const __deque_iterator<T, Ref>&) { + return 0; +} + +#endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */ + + +// See __deque_buf_size(). The only reason that the default value is 0 +// is as a workaround for bugs in the way that some compilers handle +// constant expressions. +template <class T, class Alloc = alloc, size_t BufSiz = 0> +class deque { +public: // Basic types + typedef T value_type; + typedef value_type* pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + +public: // Iterators +#ifndef __STL_NON_TYPE_TMPL_PARAM_BUG + typedef __deque_iterator<value_type, reference, BufSiz> iterator; + typedef __deque_iterator<value_type, const_reference, BufSiz> const_iterator; +#else /* __STL_NON_TYPE_TMPL_PARAM_BUG */ + typedef __deque_iterator<value_type, reference> iterator; + typedef __deque_iterator<value_type, const_reference> const_iterator; +#endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */ + typedef reverse_iterator<const_iterator, value_type, const_reference, + difference_type> + const_reverse_iterator; + typedef reverse_iterator<iterator, value_type, reference, difference_type> + reverse_iterator; + +protected: // Internal typedefs + typedef pointer* map_pointer; + typedef simple_alloc<value_type, Alloc> data_allocator; + typedef simple_alloc<pointer, Alloc> map_allocator; + + static size_type buffer_size() { + return __deque_buf_size(BufSiz, sizeof(value_type)); + } + static size_type initial_map_size() { return 8; } + +protected: // Data members + iterator start; + iterator finish; + + map_pointer map; + size_type map_size; + +public: // Basic accessors + iterator begin() { return start; } + iterator end() { return finish; } + const_iterator begin() const { return start; } + const_iterator end() const { return finish; } + + reverse_iterator rbegin() { return reverse_iterator(finish); } + reverse_iterator rend() { return reverse_iterator(start); } + const_reverse_iterator rbegin() const { + return const_reverse_iterator(finish); + } + const_reverse_iterator rend() const { + return const_reverse_iterator(start); + } + + reference operator[](size_type n) { return start[n]; } + const_reference operator[](size_type n) const { return start[n]; } + + reference front() { return *start; } + reference back() { + iterator tmp = finish; + --tmp; + return *tmp; + } + const_reference front() const { return *start; } + const_reference back() const { + const_iterator tmp = finish; + --tmp; + return *tmp; + } + + size_type size() const { return finish - start;; } + size_type max_size() const { return size_type(-1); } + bool empty() const { return finish == start; } + +public: // Constructor, destructor. + deque() + : start(), finish(), map(0), map_size(0) + { + create_map_and_nodes(0); + } + + deque(const deque& x) + : start(), finish(), map(0), map_size(0) + { + create_map_and_nodes(x.size()); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + uninitialized_copy(x.begin(), x.end(), start); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy_map_and_nodes(); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } + + deque(size_type n, const value_type& value) + : start(), finish(), map(0), map_size(0) { + fill_initialize(n, value); + } + + deque(int n, const value_type& value) + : start(), finish(), map(0), map_size(0) { + fill_initialize(n, value); + } + + deque(long n, const value_type& value) + : start(), finish(), map(0), map_size(0) { + fill_initialize(n, value); + } + + explicit deque(size_type n) + : start(), finish(), map(0), map_size(0) { + fill_initialize(n, value_type()); + } + +#ifdef __STL_MEMBER_TEMPLATES + + template <class InputIterator> + deque(InputIterator first, InputIterator last) + : start(), finish(), map(0), map_size(0) + { + range_initialize(first, last, iterator_category(first)); + } + +#else /* __STL_MEMBER_TEMPLATES */ + + deque(const value_type* first, const value_type* last) + : start(), finish(), map(0), map_size(0) + { + create_map_and_nodes(last - first); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + uninitialized_copy(first, last, start); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy_map_and_nodes(); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } + + deque(const_iterator first, const_iterator last) + : start(), finish(), map(0), map_size(0) + { + create_map_and_nodes(last - first); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + uninitialized_copy(first, last, start); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy_map_and_nodes(); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } + +#endif /* __STL_MEMBER_TEMPLATES */ + + ~deque() { + destroy(start, finish); + destroy_map_and_nodes(); + } + + deque& operator= (const deque& x) { + const size_type len = size(); + if (&x != this) { + if (len >= x.size()) + erase(copy(x.begin(), x.end(), start), finish); + else { + const_iterator mid = x.begin() + len; + copy(x.begin(), mid, start); + insert(finish, mid, x.end()); + } + } + return *this; + } + + void swap(deque& x) { + ::swap(start, x.start); + ::swap(finish, x.finish); + ::swap(map, x.map); + ::swap(map_size, x.map_size); + } + +public: // push_* and pop_* + + void push_back(const value_type& t) { + if (finish.cur != finish.last - 1) { + construct(finish.cur, t); + ++finish.cur; + } + else + push_back_aux(t); + } + + void push_front(const value_type& t) { + if (start.cur != start.first) { + construct(start.cur - 1, t); + --start.cur; + } + else + push_front_aux(t); + } + + void pop_back() { + if (finish.cur != finish.first) { + --finish.cur; + destroy(finish.cur); + } + else + pop_back_aux(); + } + + void pop_front() { + if (start.cur != start.last - 1) { + destroy(start.cur); + ++start.cur; + } + else + pop_front_aux(); + } + +public: // Insert + + iterator insert(iterator position, const value_type& x) { + if (position.cur == start.cur) { + push_front(x); + return start; + } + else if (position.cur == finish.cur) { + push_back(x); + iterator tmp = finish; + --tmp; + return tmp; + } + else { + return insert_aux(position, x); + } + } + + iterator insert(iterator position) { return insert(position, value_type()); } + + void insert(iterator pos, size_type n, const value_type& x); + + void insert(iterator pos, int n, const value_type& x) { + insert(pos, (size_type) n, x); + } + void insert(iterator pos, long n, const value_type& x) { + insert(pos, (size_type) n, x); + } + +#ifdef __STL_MEMBER_TEMPLATES + + template <class InputIterator> + void insert(iterator pos, InputIterator first, InputIterator last) { + insert(pos, first, last, iterator_category(first)); + } + +#else /* __STL_MEMBER_TEMPLATES */ + + void insert(iterator pos, const value_type* first, const value_type* last); + void insert(iterator pos, const_iterator first, const_iterator last); + +#endif /* __STL_MEMBER_TEMPLATES */ + + void resize(size_type new_size, const value_type& x) { + const size_type len = size(); + if (new_size < len) + erase(start + new_size, finish); + else + insert(finish, new_size - len, x); + } + + void resize(size_type new_size) { resize(new_size, value_type()); } + +public: // Erase + void erase(iterator pos) { + iterator next = pos; + ++next; + if (pos - start < size() / 2) { + copy_backward(start, pos, next); + pop_front(); + } + else { + copy(next, finish, pos); + pop_back(); + } + } + + void erase(iterator first, iterator last); + void clear(); + +protected: // Internal construction/destruction + + void create_map_and_nodes(size_type num_elements); + void destroy_map_and_nodes(); + void fill_initialize(size_type n, const value_type& value); + +#ifdef __STL_MEMBER_TEMPLATES + + template <class InputIterator> + void range_initialize(InputIterator first, InputIterator last, + input_iterator_tag); + + template <class ForwardIterator> + void range_initialize(ForwardIterator first, ForwardIterator last, + forward_iterator_tag); + + template <class BidirectionalIterator> + void range_initialize(BidirectionalIterator first, + BidirectionalIterator last, + bidirectional_iterator_tag) { + range_initialize(first, last, forward_iterator_tag()); + } + + template <class RandomAccessIterator> + void range_initialize(RandomAccessIterator first, RandomAccessIterator last, + random_access_iterator_tag) { + range_initialize(first, last, forward_iterator_tag()); + } + +#endif /* __STL_MEMBER_TEMPLATES */ + +protected: // Internal push_* and pop_* + + void push_back_aux(const value_type& t); + void push_front_aux(const value_type& t); + void pop_back_aux(); + void pop_front_aux(); + +protected: // Internal insert functions + +#ifdef __STL_MEMBER_TEMPLATES + + template <class InputIterator> + void insert(iterator pos, InputIterator first, InputIterator last, + input_iterator_tag); + + template <class ForwardIterator> + void insert(iterator pos, ForwardIterator first, ForwardIterator last, + forward_iterator_tag); + + template <class BidirectionalIterator> + void insert(iterator pos, + BidirectionalIterator first, BidirectionalIterator last, + bidirectional_iterator_tag) { + insert(pos, first, last, forward_iterator_tag()); + } + + template <class RandomAccessIterator> + void insert(iterator pos, + RandomAccessIterator first, RandomAccessIterator last, + random_access_iterator_tag) { + insert(pos, first, last, forward_iterator_tag()); + } +#endif /* __STL_MEMBER_TEMPLATES */ + + iterator insert_aux(iterator pos, const value_type& x); + void insert_aux(iterator pos, size_type n, const value_type& x); + +#ifdef __STL_MEMBER_TEMPLATES + + template <class ForwardIterator> + void insert_aux(iterator pos, ForwardIterator first, ForwardIterator last, + size_type n); + +#else /* __STL_MEMBER_TEMPLATES */ + + void insert_aux(iterator pos, + const value_type* first, const value_type* last, + size_type n); + + void insert_aux(iterator pos, const_iterator first, const_iterator last, + size_type n); + +#endif /* __STL_MEMBER_TEMPLATES */ + + iterator reserve_elements_at_front(size_type n) { + size_type vacancies = start.cur - start.first; + if (n > vacancies) + new_elements_at_front(n - vacancies); + return start - n; + } + + iterator reserve_elements_at_back(size_type n) { + size_type vacancies = (finish.last - finish.cur) - 1; + if (n > vacancies) + new_elements_at_back(n - vacancies); + return finish + n; + } + + void new_elements_at_front(size_type new_elements); + void new_elements_at_back(size_type new_elements); + + void destroy_nodes_at_front(iterator before_start); + void destroy_nodes_at_back(iterator after_finish); + +protected: // Allocation of map and nodes + + // Makes sure the map has space for new nodes. Does not actually + // add the nodes. Can invalidate map pointers. (And consequently, + // deque iterators.) + + void reserve_map_at_back (size_type nodes_to_add = 1) { + if (nodes_to_add + 1 > map_size - (finish.node - map)) + reallocate_map(nodes_to_add, false); + } + + void reserve_map_at_front (size_type nodes_to_add = 1) { + if (nodes_to_add > start.node - map) + reallocate_map(nodes_to_add, true); + } + + void reallocate_map(size_type nodes_to_add, bool add_at_front); + + pointer allocate_node() { return data_allocator::allocate(buffer_size()); } + void deallocate_node(pointer n) { + data_allocator::deallocate(n, buffer_size()); + } + +#ifdef __STL_NON_TYPE_TMPL_PARAM_BUG +public: + bool operator==(const deque<T, Alloc, 0>& x) const { + return size() == x.size() && equal(begin(), end(), x.begin()); + } + bool operator!=(const deque<T, Alloc, 0>& x) const { + return size() != x.size() || !equal(begin(), end(), x.begin()); + } + bool operator<(const deque<T, Alloc, 0>& x) const { + return lexicographical_compare(begin(), end(), x.begin(), x.end()); + } +#endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */ +}; + +// Non-inline member functions + +template <class T, class Alloc, size_t BufSize> +void deque<T, Alloc, BufSize>::insert(iterator pos, + size_type n, const value_type& x) { + if (pos.cur == start.cur) { + iterator new_start = reserve_elements_at_front(n); + uninitialized_fill(new_start, start, x); + start = new_start; + } + else if (pos.cur == finish.cur) { + iterator new_finish = reserve_elements_at_back(n); + uninitialized_fill(finish, new_finish, x); + finish = new_finish; + } + else + insert_aux(pos, n, x); +} + +#ifndef __STL_MEMBER_TEMPLATES + +template <class T, class Alloc, size_t BufSize> +void deque<T, Alloc, BufSize>::insert(iterator pos, + const value_type* first, + const value_type* last) { + size_type n = last - first; + if (pos.cur == start.cur) { + iterator new_start = reserve_elements_at_front(n); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif + uninitialized_copy(first, last, new_start); + start = new_start; +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy_nodes_at_front(new_start); + throw; + } +# endif + } + else if (pos.cur == finish.cur) { + iterator new_finish = reserve_elements_at_back(n); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif + uninitialized_copy(first, last, finish); + finish = new_finish; +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy_nodes_at_back(new_finish); + throw; + } +# endif + } + else + insert_aux(pos, first, last, n); +} + +template <class T, class Alloc, size_t BufSize> +void deque<T, Alloc, BufSize>::insert(iterator pos, + const_iterator first, + const_iterator last) +{ + size_type n = last - first; + if (pos.cur == start.cur) { + iterator new_start = reserve_elements_at_front(n); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif + uninitialized_copy(first, last, new_start); + start = new_start; +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy_nodes_at_front(new_start); + throw; + } +# endif + } + else if (pos.cur == finish.cur) { + iterator new_finish = reserve_elements_at_back(n); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif + uninitialized_copy(first, last, finish); + finish = new_finish; +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy_nodes_at_back(new_finish); + throw; + } +# endif + } + else + insert_aux(pos, first, last, n); +} + +#endif /* __STL_MEMBER_TEMPLATES */ + +template <class T, class Alloc, size_t BufSize> +void deque<T, Alloc, BufSize>::erase(iterator first, iterator last) { + if (first == start && last == finish) + clear(); + else { + difference_type n = last - first; + difference_type elems_before = first - start; + if (elems_before < (size() - n) / 2) { + copy_backward(start, first, last); + iterator new_start = start + n; + destroy(start, new_start); + for (map_pointer cur = start.node; cur < new_start.node; ++cur) + data_allocator::deallocate(*cur, buffer_size()); + start = new_start; + } + else { + copy(last, finish, first); + iterator new_finish = finish - n; + destroy(new_finish, finish); + for (map_pointer cur = new_finish.node + 1; cur <= finish.node; ++cur) + data_allocator::deallocate(*cur, buffer_size()); + finish = new_finish; + } + } +} + +template <class T, class Alloc, size_t BufSize> +void deque<T, Alloc, BufSize>::clear() { + for (map_pointer node = start.node + 1; node < finish.node; ++node) { + destroy(*node, *node + buffer_size()); + data_allocator::deallocate(*node, buffer_size()); + } + + if (start.node != finish.node) { + destroy(start.cur, start.last); + destroy(finish.first, finish.cur); + data_allocator::deallocate(finish.first, buffer_size()); + } + else + destroy(start.cur, finish.cur); + + finish = start; +} + +template <class T, class Alloc, size_t BufSize> +void deque<T, Alloc, BufSize>::create_map_and_nodes(size_type num_elements) { + size_type num_nodes = num_elements / buffer_size() + 1; + + map_size = max(initial_map_size(), num_nodes + 2); + map = map_allocator::allocate(map_size); + + map_pointer nstart = map + (map_size - num_nodes) / 2; + map_pointer nfinish = nstart + num_nodes - 1; + + map_pointer cur; +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + for (cur = nstart; cur <= nfinish; ++cur) + *cur = allocate_node(); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + for (map_pointer n = nstart; n < cur; ++n) + deallocate_node(*n); + map_allocator::deallocate(map, map_size); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + + start.set_node(nstart); + finish.set_node(nfinish); + start.cur = start.first; + finish.cur = finish.first + num_elements % buffer_size(); +} + +// This is only used as a cleanup function in catch clauses. +template <class T, class Alloc, size_t BufSize> +void deque<T, Alloc, BufSize>::destroy_map_and_nodes() { + for (map_pointer cur = start.node; cur <= finish.node; ++cur) + deallocate_node(*cur); + map_allocator::deallocate(map, map_size); +} + + +template <class T, class Alloc, size_t BufSize> +void deque<T, Alloc, BufSize>::fill_initialize(size_type n, + const value_type& value) { + create_map_and_nodes(n); + map_pointer cur; +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + for (cur = start.node; cur < finish.node; ++cur) + uninitialized_fill(*cur, *cur + buffer_size(), value); + uninitialized_fill(finish.first, finish.cur, value); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + for (map_pointer n = start.node; n < cur; ++n) + destroy(*cur, *cur + buffer_size()); + destroy_map_and_nodes(); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ +} + +#ifdef __STL_MEMBER_TEMPLATES + +template <class T, class Alloc, size_t BufSize> +template <class InputIterator> +void deque<T, Alloc, BufSize>::range_initialize(InputIterator first, + InputIterator last, + input_iterator_tag) { + create_map_and_nodes(0); + for ( ; first != last; ++first) + push_back(*first); +} + +template <class T, class Alloc, size_t BufSize> +template <class ForwardIterator> +void deque<T, Alloc, BufSize>::range_initialize(ForwardIterator first, + ForwardIterator last, + forward_iterator_tag) { + size_type n = 0; + distance(first, last, n); + create_map_and_nodes(n); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + uninitialized_copy(first, last, start); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy_map_and_nodes(); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ +} + +#endif /* __STL_MEMBER_TEMPLATES */ + +// Called only if finish.cur == finish.last - 1. +template <class T, class Alloc, size_t BufSize> +void deque<T, Alloc, BufSize>::push_back_aux(const value_type& t) { + value_type t_copy = t; + reserve_map_at_back(); + *(finish.node + 1) = allocate_node(); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + construct(finish.cur, t_copy); + finish.set_node(finish.node + 1); + finish.cur = finish.first; +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + deallocate_node(*(finish.node + 1)); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ +} + +// Called only if start.cur == start.first. +template <class T, class Alloc, size_t BufSize> +void deque<T, Alloc, BufSize>::push_front_aux(const value_type& t) { + value_type t_copy = t; + reserve_map_at_front(); + *(start.node - 1) = allocate_node(); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + start.set_node(start.node - 1); + start.cur = start.last - 1; + construct(start.cur, t_copy); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + start.set_node(start.node + 1); + start.cur = start.first; + deallocate_node(*(start.node - 1)); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ +} + +// Called only if finish.cur == finish.first. +template <class T, class Alloc, size_t BufSize> +void deque<T, Alloc, BufSize>:: pop_back_aux() { + deallocate_node(finish.first); + finish.set_node(finish.node - 1); + finish.cur = finish.last - 1; + destroy(finish.cur); +} + +// Called only if start.cur == start.last - 1. Note that if the deque +// has at least one element (a necessary precondition for this member +// function), and if start.cur == start.last, then the deque must have +// at least two nodes. +template <class T, class Alloc, size_t BufSize> +void deque<T, Alloc, BufSize>::pop_front_aux() { + destroy(start.cur); + deallocate_node(start.first); + start.set_node(start.node + 1); + start.cur = start.first; +} + +#ifdef __STL_MEMBER_TEMPLATES + +template <class T, class Alloc, size_t BufSize> +template <class InputIterator> +void deque<T, Alloc, BufSize>::insert(iterator pos, + InputIterator first, InputIterator last, + input_iterator_tag) { + copy(first, last, inserter(*this, pos)); +} + +template <class T, class Alloc, size_t BufSize> +template <class ForwardIterator> +void deque<T, Alloc, BufSize>::insert(iterator pos, + ForwardIterator first, + ForwardIterator last, + forward_iterator_tag) { + size_type n = 0; + distance(first, last, n); + if (pos.cur == start.cur) { + iterator new_start = reserve_elements_at_front(n); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif + uninitialized_copy(first, last, new_start); + start = new_start; +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy_nodes_at_front(new_start); + throw; + } +# endif + } + else if (pos.cur == finish.cur) { + iterator new_finish = reserve_elements_at_back(n); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif + uninitialized_copy(first, last, finish); + finish = new_finish; +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy_nodes_at_back(new_finish); + throw; + } +# endif + } + else + insert_aux(pos, first, last, n); +} + +#endif /* __STL_MEMBER_TEMPLATES */ + +template <class T, class Alloc, size_t BufSize> +deque<T, Alloc, BufSize>::iterator +deque<T, Alloc, BufSize>::insert_aux(iterator pos, const value_type& x) { + difference_type index = pos - start; + value_type x_copy = x; + if (index < size() / 2) { + push_front(front()); + iterator front1 = start; + ++front1; + iterator front2 = front1; + ++front2; + pos = start + index; + iterator pos1 = pos; + ++pos1; + copy(front2, pos1, front1); + } + else { + push_back(back()); + iterator back1 = finish; + --back1; + iterator back2 = back1; + --back2; + pos = start + index; + copy_backward(pos, back2, back1); + } + *pos = x_copy; + return pos; +} + +template <class T, class Alloc, size_t BufSize> +void deque<T, Alloc, BufSize>::insert_aux(iterator pos, + size_type n, const value_type& x) { + const difference_type elems_before = pos - start; + size_type length = size(); + value_type x_copy = x; + if (elems_before < length / 2) { + iterator new_start = reserve_elements_at_front(n); + iterator old_start = start; + pos = start + elems_before; +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + if (elems_before >= n) { + iterator start_n = start + n; + uninitialized_copy(start, start_n, new_start); + start = new_start; + copy(start_n, pos, old_start); + fill(pos - n, pos, x_copy); + } + else { + __uninitialized_copy_fill(start, pos, new_start, start, x_copy); + start = new_start; + fill(old_start, pos, x_copy); + } +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy_nodes_at_front(new_start); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } + else { + iterator new_finish = reserve_elements_at_back(n); + iterator old_finish = finish; + const difference_type elems_after = length - elems_before; + pos = finish - elems_after; +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + if (elems_after > n) { + iterator finish_n = finish - n; + uninitialized_copy(finish_n, finish, finish); + finish = new_finish; + copy_backward(pos, finish_n, old_finish); + fill(pos, pos + n, x_copy); + } + else { + __uninitialized_fill_copy(finish, pos + n, x_copy, pos, finish); + finish = new_finish; + fill(pos, old_finish, x_copy); + } +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy_nodes_at_back(new_finish); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } +} + +#ifdef __STL_MEMBER_TEMPLATES + +template <class T, class Alloc, size_t BufSize> +template <class ForwardIterator> +void deque<T, Alloc, BufSize>::insert_aux(iterator pos, + ForwardIterator first, + ForwardIterator last, + size_type n) +{ + const difference_type elems_before = pos - start; + size_type length = size(); + if (elems_before < length / 2) { + iterator new_start = reserve_elements_at_front(n); + iterator old_start = start; + pos = start + elems_before; +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + if (elems_before >= n) { + iterator start_n = start + n; + uninitialized_copy(start, start_n, new_start); + start = new_start; + copy(start_n, pos, old_start); + copy(first, last, pos - n); + } + else { + ForwardIterator mid = first; + advance(mid, n - elems_before); + __uninitialized_copy_copy(start, pos, first, mid, new_start); + start = new_start; + copy(mid, last, old_start); + } +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy_nodes_at_front(new_start); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } + else { + iterator new_finish = reserve_elements_at_back(n); + iterator old_finish = finish; + const difference_type elems_after = length - elems_before; + pos = finish - elems_after; +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + if (elems_after > n) { + iterator finish_n = finish - n; + uninitialized_copy(finish_n, finish, finish); + finish = new_finish; + copy_backward(pos, finish_n, old_finish); + copy(first, last, pos); + } + else { + ForwardIterator mid = first; + advance(mid, elems_after); + __uninitialized_copy_copy(mid, last, pos, finish, finish); + finish = new_finish; + copy(first, mid, pos); + } +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy_nodes_at_back(new_finish); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } +} + +#else /* __STL_MEMBER_TEMPLATES */ + +template <class T, class Alloc, size_t BufSize> +void deque<T, Alloc, BufSize>::insert_aux(iterator pos, + const value_type* first, + const value_type* last, + size_type n) +{ + const difference_type elems_before = pos - start; + size_type length = size(); + if (elems_before < length / 2) { + iterator new_start = reserve_elements_at_front(n); + iterator old_start = start; + pos = start + elems_before; +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + if (elems_before >= n) { + iterator start_n = start + n; + uninitialized_copy(start, start_n, new_start); + start = new_start; + copy(start_n, pos, old_start); + copy(first, last, pos - n); + } + else { + const value_type* mid = first + (n - elems_before); + __uninitialized_copy_copy(start, pos, first, mid, new_start); + start = new_start; + copy(mid, last, old_start); + } +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy_nodes_at_front(new_start); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } + else { + iterator new_finish = reserve_elements_at_back(n); + iterator old_finish = finish; + const difference_type elems_after = length - elems_before; + pos = finish - elems_after; +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + if (elems_after > n) { + iterator finish_n = finish - n; + uninitialized_copy(finish_n, finish, finish); + finish = new_finish; + copy_backward(pos, finish_n, old_finish); + copy(first, last, pos); + } + else { + const value_type* mid = first + elems_after; + __uninitialized_copy_copy(mid, last, pos, finish, finish); + finish = new_finish; + copy(first, mid, pos); + } +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy_nodes_at_back(new_finish); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } +} + +template <class T, class Alloc, size_t BufSize> +void deque<T, Alloc, BufSize>::insert_aux(iterator pos, + const_iterator first, + const_iterator last, + size_type n) +{ + const difference_type elems_before = pos - start; + size_type length = size(); + if (elems_before < length / 2) { + iterator new_start = reserve_elements_at_front(n); + iterator old_start = start; + pos = start + elems_before; +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + if (elems_before >= n) { + iterator start_n = start + n; + uninitialized_copy(start, start_n, new_start); + start = new_start; + copy(start_n, pos, old_start); + copy(first, last, pos - n); + } + else { + const_iterator mid = first + (n - elems_before); + __uninitialized_copy_copy(start, pos, first, mid, new_start); + start = new_start; + copy(mid, last, old_start); + } +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy_nodes_at_front(new_start); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } + else { + iterator new_finish = reserve_elements_at_back(n); + iterator old_finish = finish; + const difference_type elems_after = length - elems_before; + pos = finish - elems_after; +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + if (elems_after > n) { + iterator finish_n = finish - n; + uninitialized_copy(finish_n, finish, finish); + finish = new_finish; + copy_backward(pos, finish_n, old_finish); + copy(first, last, pos); + } + else { + const_iterator mid = first + elems_after; + __uninitialized_copy_copy(mid, last, pos, finish, finish); + finish = new_finish; + copy(first, mid, pos); + } +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy_nodes_at_back(new_finish); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } +} + +#endif /* __STL_MEMBER_TEMPLATES */ + +template <class T, class Alloc, size_t BufSize> +void deque<T, Alloc, BufSize>::new_elements_at_front(size_type new_elements) { + size_type new_nodes = (new_elements + buffer_size() - 1) / buffer_size(); + reserve_map_at_front(new_nodes); + size_type i; +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + for (i = 1; i <= new_nodes; ++i) + *(start.node - i) = allocate_node(); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + for (size_type j = 1; j < i; ++j) + deallocate_node(*(start.node - j)); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ +} + +template <class T, class Alloc, size_t BufSize> +void deque<T, Alloc, BufSize>::new_elements_at_back(size_type new_elements) { + size_type new_nodes = (new_elements + buffer_size() - 1) / buffer_size(); + reserve_map_at_back(new_nodes); + size_type i; +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + for (i = 1; i <= new_nodes; ++i) + *(finish.node + i) = allocate_node(); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + for (size_type j = 1; j < i; ++j) + deallocate_node(*(finish.node + j)); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ +} + +template <class T, class Alloc, size_t BufSize> +void deque<T, Alloc, BufSize>::destroy_nodes_at_front(iterator before_start) { + for (map_pointer n = before_start.node; n < start.node; ++n) + deallocate_node(*n); +} + +template <class T, class Alloc, size_t BufSize> +void deque<T, Alloc, BufSize>::destroy_nodes_at_back(iterator after_finish) { + for (map_pointer n = after_finish.node; n > finish.node; --n) + deallocate_node(*n); +} + +template <class T, class Alloc, size_t BufSize> +void deque<T, Alloc, BufSize>::reallocate_map(size_type nodes_to_add, + bool add_at_front) { + size_type old_num_nodes = finish.node - start.node + 1; + size_type new_num_nodes = old_num_nodes + nodes_to_add; + + map_pointer new_nstart; + if (map_size > 2 * new_num_nodes) { + new_nstart = map + (map_size - new_num_nodes) / 2 + + (add_at_front ? nodes_to_add : 0); + if (new_nstart < start.node) + copy(start.node, finish.node + 1, new_nstart); + else + copy_backward(start.node, finish.node + 1, new_nstart + old_num_nodes); + } + else { + size_type new_map_size = map_size + max(map_size, nodes_to_add) + 2; + + map_pointer new_map = map_allocator::allocate(new_map_size); + new_nstart = new_map + (new_map_size - new_num_nodes) / 2 + + (add_at_front ? nodes_to_add : 0); + copy(start.node, finish.node + 1, new_nstart); + map_allocator::deallocate(map, map_size); + + map = new_map; + map_size = new_map_size; + } + + start.set_node(new_nstart); + finish.set_node(new_nstart + old_num_nodes - 1); +} + + +// Nonmember functions. + +#ifndef __STL_NON_TYPE_TMPL_PARAM_BUG + +template <class T, class Alloc, size_t BufSiz> +bool operator==(const deque<T, Alloc, BufSiz>& x, + const deque<T, Alloc, BufSiz>& y) { + return x.size() == y.size() && equal(x.begin(), x.end(), y.begin()); +} + +template <class T, class Alloc, size_t BufSiz> +bool operator<(const deque<T, Alloc, BufSiz>& x, + const deque<T, Alloc, BufSiz>& y) { + return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); +} + +#endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */ + + +#endif /* __SGI_STL_DEQUE_H */ + diff --git a/libstdc++/stl/function.h b/libstdc++/stl/function.h new file mode 100644 index 0000000..e4f4713 --- /dev/null +++ b/libstdc++/stl/function.h @@ -0,0 +1,634 @@ +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#ifndef __SGI_STL_FUNCTION_H +#define __SGI_STL_FUNCTION_H + +#include <stddef.h> +#include <stl_config.h> + +template <class T> +inline bool operator!=(const T& x, const T& y) { + return !(x == y); +} + +template <class T> +inline bool operator>(const T& x, const T& y) { + return y < x; +} + +template <class T> +inline bool operator<=(const T& x, const T& y) { + return !(y < x); +} + +template <class T> +inline bool operator>=(const T& x, const T& y) { + return !(x < y); +} + +template <class Arg, class Result> +struct unary_function { + typedef Arg argument_type; + typedef Result result_type; +}; + +template <class Arg1, class Arg2, class Result> +struct binary_function { + typedef Arg1 first_argument_type; + typedef Arg2 second_argument_type; + typedef Result result_type; +}; + +template <class T> +struct plus : public binary_function<T, T, T> { + T operator()(const T& x, const T& y) const { return x + y; } +}; + +template <class T> +struct minus : public binary_function<T, T, T> { + T operator()(const T& x, const T& y) const { return x - y; } +}; + +template <class T> +struct multiplies : public binary_function<T, T, T> { + T operator()(const T& x, const T& y) const { return x * y; } +}; + +template <class T> +struct divides : public binary_function<T, T, T> { + T operator()(const T& x, const T& y) const { return x / y; } +}; + +template <class T> inline T identity_element(plus<T>) { return T(0); } + +template <class T> inline T identity_element(multiplies<T>) { return T(1); } + +template <class T> +struct modulus : public binary_function<T, T, T> { + T operator()(const T& x, const T& y) const { return x % y; } +}; + +template <class T> +struct negate : public unary_function<T, T> { + T operator()(const T& x) const { return -x; } +}; + +template <class T> +struct equal_to : public binary_function<T, T, bool> { + bool operator()(const T& x, const T& y) const { return x == y; } +}; + +template <class T> +struct not_equal_to : public binary_function<T, T, bool> { + bool operator()(const T& x, const T& y) const { return x != y; } +}; + +template <class T> +struct greater : public binary_function<T, T, bool> { + bool operator()(const T& x, const T& y) const { return x > y; } +}; + +template <class T> +struct less : public binary_function<T, T, bool> { + bool operator()(const T& x, const T& y) const { return x < y; } +}; + +template <class T> +struct greater_equal : public binary_function<T, T, bool> { + bool operator()(const T& x, const T& y) const { return x >= y; } +}; + +template <class T> +struct less_equal : public binary_function<T, T, bool> { + bool operator()(const T& x, const T& y) const { return x <= y; } +}; + +template <class T> +struct logical_and : public binary_function<T, T, bool> { + bool operator()(const T& x, const T& y) const { return x && y; } +}; + +template <class T> +struct logical_or : public binary_function<T, T, bool> { + bool operator()(const T& x, const T& y) const { return x || y; } +}; + +template <class T> +struct logical_not : public unary_function<T, bool> { + bool operator()(const T& x) const { return !x; } +}; + +template <class Predicate> +class unary_negate + : public unary_function<typename Predicate::argument_type, bool> { +protected: + Predicate pred; +public: + explicit unary_negate(const Predicate& x) : pred(x) {} + bool operator()(const argument_type& x) const { return !pred(x); } +}; + +template <class Predicate> +inline unary_negate<Predicate> not1(const Predicate& pred) { + return unary_negate<Predicate>(pred); +} + +template <class Predicate> +class binary_negate + : public binary_function<typename Predicate::first_argument_type, + typename Predicate::second_argument_type, + bool> { +protected: + Predicate pred; +public: + explicit binary_negate(const Predicate& x) : pred(x) {} + bool operator()(const first_argument_type& x, + const second_argument_type& y) const { + return !pred(x, y); + } +}; + +template <class Predicate> +inline binary_negate<Predicate> not2(const Predicate& pred) { + return binary_negate<Predicate>(pred); +} + +template <class Operation> +class binder1st + : public unary_function<typename Operation::second_argument_type, + typename Operation::result_type> { +protected: + Operation op; + typename Operation::first_argument_type value; +public: + binder1st(const Operation& x, + const typename Operation::first_argument_type& y) + : op(x), value(y) {} + result_type operator()(const argument_type& x) const { + return op(value, x); + } +}; + +template <class Operation, class T> +inline binder1st<Operation> bind1st(const Operation& op, const T& x) { + typedef typename Operation::first_argument_type arg1_type; + return binder1st<Operation>(op, arg1_type(x)); +} + +template <class Operation> +class binder2nd + : public unary_function<typename Operation::first_argument_type, + typename Operation::result_type> { +protected: + Operation op; + typename Operation::second_argument_type value; +public: + binder2nd(const Operation& x, + const typename Operation::second_argument_type& y) + : op(x), value(y) {} + result_type operator()(const argument_type& x) const { + return op(x, value); + } +}; + +template <class Operation, class T> +inline binder2nd<Operation> bind2nd(const Operation& op, const T& x) { + typedef typename Operation::second_argument_type arg2_type; + return binder2nd<Operation>(op, arg2_type(x)); +} + +template <class Operation1, class Operation2> +class unary_compose : public unary_function<typename Operation2::argument_type, + typename Operation1::result_type> { +protected: + Operation1 op1; + Operation2 op2; +public: + unary_compose(const Operation1& x, const Operation2& y) : op1(x), op2(y) {} + result_type operator()(const argument_type& x) const { + return op1(op2(x)); + } +}; + +template <class Operation1, class Operation2> +inline unary_compose<Operation1, Operation2> compose1(const Operation1& op1, + const Operation2& op2) { + return unary_compose<Operation1, Operation2>(op1, op2); +} + +template <class Operation1, class Operation2, class Operation3> +class binary_compose + : public unary_function<typename Operation2::argument_type, + typename Operation1::result_type> { +protected: + Operation1 op1; + Operation2 op2; + Operation3 op3; +public: + binary_compose(const Operation1& x, const Operation2& y, + const Operation3& z) : op1(x), op2(y), op3(z) { } + result_type operator()(const argument_type& x) const { + return op1(op2(x), op3(x)); + } +}; + +template <class Operation1, class Operation2, class Operation3> +inline binary_compose<Operation1, Operation2, Operation3> +compose2(const Operation1& op1, const Operation2& op2, const Operation3& op3) { + return binary_compose<Operation1, Operation2, Operation3>(op1, op2, op3); +} + +template <class Arg, class Result> +class pointer_to_unary_function : public unary_function<Arg, Result> { +protected: + Result (*ptr)(Arg); +public: + pointer_to_unary_function() {} + explicit pointer_to_unary_function(Result (*x)(Arg)) : ptr(x) {} + Result operator()(Arg x) const { return ptr(x); } +}; + +template <class Arg, class Result> +inline pointer_to_unary_function<Arg, Result> ptr_fun(Result (*x)(Arg)) { + return pointer_to_unary_function<Arg, Result>(x); +} + +template <class Arg1, class Arg2, class Result> +class pointer_to_binary_function : public binary_function<Arg1, Arg2, Result> { +protected: + Result (*ptr)(Arg1, Arg2); +public: + pointer_to_binary_function() {} + explicit pointer_to_binary_function(Result (*x)(Arg1, Arg2)) : ptr(x) {} + Result operator()(Arg1 x, Arg2 y) const { return ptr(x, y); } +}; + +template <class Arg1, class Arg2, class Result> +inline pointer_to_binary_function<Arg1, Arg2, Result> +ptr_fun(Result (*x)(Arg1, Arg2)) { + return pointer_to_binary_function<Arg1, Arg2, Result>(x); +} + +template <class T> +struct identity : public unary_function<T, T> { + const T& operator()(const T& x) const { return x; } +}; + +template <class Pair> +struct select1st : public unary_function<Pair, typename Pair::first_type> { + const typename Pair::first_type& operator()(const Pair& x) const + { + return x.first; + } +}; + +template <class Pair> +struct select2nd : public unary_function<Pair, typename Pair::second_type> { + const typename Pair::second_type& operator()(const Pair& x) const + { + return x.second; + } +}; + +template <class Arg1, class Arg2> +struct project1st : public binary_function<Arg1, Arg2, Arg1> { + Arg1 operator()(const Arg1& x, const Arg2&) const { return x; } +}; + +template <class Arg1, class Arg2> +struct project2nd : public binary_function<Arg1, Arg2, Arg2> { + Arg2 operator()(const Arg1&, const Arg2& y) const { return y; } +}; + +template <class Result> +struct constant_void_fun +{ + typedef Result result_type; + result_type val; + constant_void_fun(const result_type& v) : val(v) {} + const result_type& operator()() const { return val; } +}; + +#ifndef __STL_LIMITED_DEFAULT_TEMPLATES +template <class Result, class Argument = Result> +#else +template <class Result, class Argument> +#endif +struct constant_unary_fun : public unary_function<Argument, Result> { + result_type val; + constant_unary_fun(const result_type& v) : val(v) {} + const result_type& operator()(const argument_type&) const { return val; } +}; + +#ifndef __STL_LIMITED_DEFAULT_TEMPLATES +template <class Result, class Arg1 = Result, class Arg2 = Arg1> +#else +template <class Result, class Arg1, class Arg2> +#endif +struct constant_binary_fun : public binary_function<Arg1, Arg2, Result> { + result_type val; + constant_binary_fun(const result_type& v) : val(v) {} + const result_type& operator()(const first_argument_type&, + const second_argument_type&) const { + return val; + } +}; + +template <class Result> +inline constant_void_fun<Result> constant0(const Result& val) +{ + return constant_void_fun<Result>(val); +} + +template <class Result> +inline constant_unary_fun<Result,Result> constant1(const Result& val) +{ + return constant_unary_fun<Result,Result>(val); +} + +template <class Result> +inline constant_binary_fun<Result,Result,Result> constant2(const Result& val) +{ + return constant_binary_fun<Result,Result,Result>(val); +} + +// Note: this code assumes that int is 32 bits. +class subtractive_rng : public unary_function<unsigned int, unsigned int> { +private: + unsigned int table[55]; + size_t index1; + size_t index2; +public: + unsigned int operator()(unsigned int limit) { + index1 = (index1 + 1) % 55; + index2 = (index2 + 1) % 55; + table[index1] = table[index1] - table[index2]; + return table[index1] % limit; + } + + void initialize(unsigned int seed) + { + unsigned int k = 1; + table[54] = seed; + size_t i; + for (i = 0; i < 54; i++) { + size_t ii = (21 * (i + 1) % 55) - 1; + table[ii] = k; + k = seed - k; + seed = table[ii]; + } + for (int loop = 0; loop < 4; loop++) { + for (i = 0; i < 55; i++) + table[i] = table[i] - table[(1 + i + 30) % 55]; + } + index1 = 0; + index2 = 31; + } + + subtractive_rng(unsigned int seed) { initialize(seed); } + subtractive_rng() { initialize(161803398u); } +}; + + +// Adaptor function objects: pointers to member functions. + +// There are a total of 16 = 2^4 function objects in this family. +// (1) Member functions taking no arguments vs member functions taking +// one argument. +// (2) Call through pointer vs call through reference. +// (3) Member function with void return type vs member function with +// non-void return type. +// (4) Const vs non-const member function. + +// Note that choice (4) is not present in the 8/97 draft C++ standard, +// which only allows these adaptors to be used with non-const functions. +// This is likely to be recified before the standard becomes final. +// Note also that choice (3) is nothing more than a workaround: according +// to the draft, compilers should handle void and non-void the same way. +// This feature is not yet widely implemented, though. You can only use +// member functions returning void if your compiler supports partial +// specialization. + +// All of this complexity is in the function objects themselves. You can +// ignore it by using the helper function mem_fun, mem_fun_ref, +// mem_fun1, and mem_fun1_ref, which create whichever type of adaptor +// is appropriate. + + +template <class S, class T> +class mem_fun_t : public unary_function<T*, S> { +public: + explicit mem_fun_t(S (T::*pf)()) : f(pf) {} + S operator()(T* p) const { return (p->*f)(); } +private: + S (T::*f)(); +}; + +template <class S, class T> +class const_mem_fun_t : public unary_function<const T*, S> { +public: + explicit const_mem_fun_t(S (T::*pf)() const) : f(pf) {} + S operator()(const T* p) const { return (p->*f)(); } +private: + S (T::*f)() const; +}; + + +template <class S, class T> +class mem_fun_ref_t : public unary_function<T, S> { +public: + explicit mem_fun_ref_t(S (T::*pf)()) : f(pf) {} + S operator()(T& r) const { return (r.*f)(); } +private: + S (T::*f)(); +}; + +template <class S, class T> +class const_mem_fun_ref_t : public unary_function<T, S> { +public: + explicit const_mem_fun_ref_t(S (T::*pf)() const) : f(pf) {} + S operator()(const T& r) const { return (r.*f)(); } +private: + S (T::*f)() const; +}; + +template <class S, class T, class A> +class mem_fun1_t : public binary_function<T*, A, S> { +public: + explicit mem_fun1_t(S (T::*pf)(A)) : f(pf) {} + S operator()(T* p, A x) const { return (p->*f)(x); } +private: + S (T::*f)(A); +}; + +template <class S, class T, class A> +class const_mem_fun1_t : public binary_function<const T*, A, S> { +public: + explicit const_mem_fun1_t(S (T::*pf)(A) const) : f(pf) {} + S operator()(const T* p, A x) const { return (p->*f)(x); } +private: + S (T::*f)(A) const; +}; + +template <class S, class T, class A> +class mem_fun1_ref_t : public binary_function<T, A, S> { +public: + explicit mem_fun1_ref_t(S (T::*pf)(A)) : f(pf) {} + S operator()(T& r, A x) const { return (r.*f)(x); } +private: + S (T::*f)(A); +}; + +template <class S, class T, class A> +class const_mem_fun1_ref_t : public binary_function<T, A, S> { +public: + explicit const_mem_fun1_ref_t(S (T::*pf)(A) const) : f(pf) {} + S operator()(const T& r, A x) const { return (r.*f)(x); } +private: + S (T::*f)(A) const; +}; + +#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION + +template <class T> +class mem_fun_t<void, T> : public unary_function<T*, void> { +public: + explicit mem_fun_t(void (T::*pf)()) : f(pf) {} + void operator()(T* p) const { (p->*f)(); } +private: + void (T::*f)(); +}; + +template <class T> +class const_mem_fun_t<void, T> : public unary_function<const T*, void> { +public: + explicit const_mem_fun_t(void (T::*pf)() const) : f(pf) {} + void operator()(const T* p) const { (p->*f)(); } +private: + void (T::*f)() const; +}; + +template <class T> +class mem_fun_ref_t<void, T> : public unary_function<T, void> { +public: + explicit mem_fun_ref_t(void (T::*pf)()) : f(pf) {} + void operator()(T& r) const { (r.*f)(); } +private: + void (T::*f)(); +}; + +template <class T> +class const_mem_fun_ref_t<void, T> : public unary_function<T, void> { +public: + explicit const_mem_fun_ref_t(void (T::*pf)() const) : f(pf) {} + void operator()(const T& r) const { (r.*f)(); } +private: + void (T::*f)() const; +}; + +template <class T, class A> +class mem_fun1_t<void, T, A> : public binary_function<T*, A, void> { +public: + explicit mem_fun1_t(void (T::*pf)(A)) : f(pf) {} + void operator()(T* p, A x) const { (p->*f)(x); } +private: + void (T::*f)(A); +}; + +template <class T, class A> +class const_mem_fun1_t<void, T, A> : public binary_function<const T*, A, void> { +public: + explicit const_mem_fun1_t(void (T::*pf)(A) const) : f(pf) {} + void operator()(const T* p, A x) const { (p->*f)(x); } +private: + void (T::*f)(A) const; +}; + +template <class T, class A> +class mem_fun1_ref_t<void, T, A> : public binary_function<T, A, void> { +public: + explicit mem_fun1_ref_t(void (T::*pf)(A)) : f(pf) {} + void operator()(T& r, A x) const { (r.*f)(x); } +private: + void (T::*f)(A); +}; + +template <class T, class A> +class const_mem_fun1_ref_t<void, T, A> : public binary_function<T, A, void> { +public: + explicit const_mem_fun1_ref_t(void (T::*pf)(A) const) : f(pf) {} + void operator()(const T& r, A x) const { (r.*f)(x); } +private: + void (T::*f)(A) const; +}; + +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +// Mem_fun adaptor helper functions. There are only four: +// mem_fun, mem_fun_ref, mem_fun1, mem_fun1_ref. + +template <class S, class T> +inline mem_fun_t<S,T> mem_fun(S (T::*f)()) { + return mem_fun_t<S,T>(f); +} + +template <class S, class T> +inline const_mem_fun_t<S,T> mem_fun(S (T::*f)() const) { + return const_mem_fun_t<S,T>(f); +} + +template <class S, class T> +inline mem_fun_ref_t<S,T> mem_fun_ref(S (T::*f)()) { + return mem_fun_ref_t<S,T>(f); +} + +template <class S, class T> +inline const_mem_fun_ref_t<S,T> mem_fun_ref(S (T::*f)() const) { + return const_mem_fun_ref_t<S,T>(f); +} + +template <class S, class T, class A> +inline mem_fun1_t<S,T,A> mem_fun1(S (T::*f)(A)) { + return mem_fun1_t<S,T,A>(f); +} + +template <class S, class T, class A> +inline const_mem_fun1_t<S,T,A> mem_fun1(S (T::*f)(A) const) { + return const_mem_fun1_t<S,T,A>(f); +} + +template <class S, class T, class A> +inline mem_fun1_ref_t<S,T,A> mem_fun1_ref(S (T::*f)(A)) { + return mem_fun1_ref_t<S,T,A>(f); +} + +template <class S, class T, class A> +inline const_mem_fun1_ref_t<S,T,A> mem_fun1_ref(S (T::*f)(A) const) { + return const_mem_fun1_ref_t<S,T,A>(f); +} + +#endif /* __SGI_STL_FUNCTION_H */ diff --git a/libstdc++/stl/hash_map.h b/libstdc++/stl/hash_map.h new file mode 100644 index 0000000..c52b993 --- /dev/null +++ b/libstdc++/stl/hash_map.h @@ -0,0 +1,319 @@ +/* + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef __SGI_STL_HASH_MAP_H +#define __SGI_STL_HASH_MAP_H + +#ifndef __SGI_STL_HASHTABLE_H +#include <hashtable.h> +#endif /* __SGI_STL_HASHTABLE_H */ + + +#ifndef __STL_LIMITED_DEFAULT_TEMPLATES +template <class Key, class T, class HashFcn = hash<Key>, + class EqualKey = equal_to<Key>, + class Alloc = alloc> +#else +template <class Key, class T, class HashFcn, class EqualKey, + class Alloc = alloc> +#endif +class hash_map +{ +private: + typedef hashtable<pair<const Key, T>, Key, HashFcn, + select1st<pair<const Key, T> >, EqualKey, Alloc> ht; + ht rep; + +public: + typedef ht::key_type key_type; + typedef ht::value_type value_type; + typedef ht::hasher hasher; + typedef ht::key_equal key_equal; + typedef T data_type; + + typedef ht::size_type size_type; + typedef ht::difference_type difference_type; + typedef ht::pointer pointer; + typedef ht::const_pointer const_pointer; + typedef ht::reference reference; + typedef ht::const_reference const_reference; + + typedef ht::iterator iterator; + typedef ht::const_iterator const_iterator; + + hasher hash_funct() const { return rep.hash_funct(); } + key_equal key_eq() const { return rep.key_eq(); } + +public: + hash_map() : rep(100, hasher(), key_equal()) {} + explicit hash_map(size_type n) : rep(n, hasher(), key_equal()) {} + hash_map(size_type n, const hasher& hf) : rep(n, hf, key_equal()) {} + hash_map(size_type n, const hasher& hf, const key_equal& eql) + : rep(n, hf, eql) {} + +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + hash_map(InputIterator f, InputIterator l) + : rep(100, hasher(), key_equal()) { rep.insert_unique(f, l); } + template <class InputIterator> + hash_map(InputIterator f, InputIterator l, size_type n) + : rep(n, hasher(), key_equal()) { rep.insert_unique(f, l); } + template <class InputIterator> + hash_map(InputIterator f, InputIterator l, size_type n, + const hasher& hf) + : rep(n, hf, key_equal()) { rep.insert_unique(f, l); } + template <class InputIterator> + hash_map(InputIterator f, InputIterator l, size_type n, + const hasher& hf, const key_equal& eql) + : rep(n, hf, eql) { rep.insert_unique(f, l); } + +#else + hash_map(const value_type* f, const value_type* l) + : rep(100, hasher(), key_equal()) { rep.insert_unique(f, l); } + hash_map(const value_type* f, const value_type* l, size_type n) + : rep(n, hasher(), key_equal()) { rep.insert_unique(f, l); } + hash_map(const value_type* f, const value_type* l, size_type n, + const hasher& hf) + : rep(n, hf, key_equal()) { rep.insert_unique(f, l); } + hash_map(const value_type* f, const value_type* l, size_type n, + const hasher& hf, const key_equal& eql) + : rep(n, hf, eql) { rep.insert_unique(f, l); } + + hash_map(const_iterator f, const_iterator l) + : rep(100, hasher(), key_equal()) { rep.insert_unique(f, l); } + hash_map(const_iterator f, const_iterator l, size_type n) + : rep(n, hasher(), key_equal()) { rep.insert_unique(f, l); } + hash_map(const_iterator f, const_iterator l, size_type n, + const hasher& hf) + : rep(n, hf, key_equal()) { rep.insert_unique(f, l); } + hash_map(const_iterator f, const_iterator l, size_type n, + const hasher& hf, const key_equal& eql) + : rep(n, hf, eql) { rep.insert_unique(f, l); } +#endif /*__STL_MEMBER_TEMPLATES */ + +public: + size_type size() const { return rep.size(); } + size_type max_size() const { return rep.max_size(); } + bool empty() const { return rep.empty(); } + void swap(hash_map& hs) { rep.swap(hs.rep); } + friend bool operator==(const hash_map<Key,T,HashFcn,EqualKey,Alloc>&, + const hash_map<Key,T,HashFcn,EqualKey,Alloc>&); + + iterator begin() { return rep.begin(); } + iterator end() { return rep.end(); } + const_iterator begin() const { return rep.begin(); } + const_iterator end() const { return rep.end(); } + +public: + pair<iterator, bool> insert(const value_type& obj) + { return rep.insert_unique(obj); } +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + void insert(InputIterator f, InputIterator l) { rep.insert_unique(f,l); } +#else + void insert(const value_type* f, const value_type* l) { + rep.insert_unique(f,l); + } + void insert(const_iterator f, const_iterator l) { rep.insert_unique(f, l); } +#endif /*__STL_MEMBER_TEMPLATES */ + pair<iterator, bool> insert_noresize(const value_type& obj) + { return rep.insert_unique_noresize(obj); } + + iterator find(const key_type& key) { return rep.find(key); } + const_iterator find(const key_type& key) const { return rep.find(key); } + + T& operator[](const key_type& key) + { + return rep.find_or_insert(value_type(key, T())).second; + } + + size_type count(const key_type& key) const { return rep.count(key); } + + pair<iterator, iterator> equal_range(const key_type& key) + { return rep.equal_range(key); } + pair<const_iterator, const_iterator> equal_range(const key_type& key) const + { return rep.equal_range(key); } + + size_type erase(const key_type& key) {return rep.erase(key); } + void erase(iterator it) { rep.erase(it); } + void erase(iterator f, iterator l) { rep.erase(f, l); } + void clear() { rep.clear(); } + +public: + void resize(size_type hint) { rep.resize(hint); } + size_type bucket_count() const { return rep.bucket_count(); } + size_type max_bucket_count() const { return rep.max_bucket_count(); } + size_type elems_in_bucket(size_type n) const + { return rep.elems_in_bucket(n); } +}; + +template <class Key, class T, class HashFcn, class EqualKey, class Alloc> +inline bool operator==(const hash_map<Key, T, HashFcn, EqualKey, Alloc>& hm1, + const hash_map<Key, T, HashFcn, EqualKey, Alloc>& hm2) +{ + return hm1.rep == hm2.rep; +} + +#ifndef __STL_LIMITED_DEFAULT_TEMPLATES +template <class Key, class T, class HashFcn = hash<Key>, + class EqualKey = equal_to<Key>, + class Alloc = alloc> +#else +template <class Key, class T, class HashFcn, class EqualKey, + class Alloc = alloc> +#endif +class hash_multimap +{ +private: + typedef hashtable<pair<const Key, T>, Key, HashFcn, + select1st<pair<const Key, T> >, EqualKey, Alloc> ht; + ht rep; + +public: + typedef ht::key_type key_type; + typedef ht::value_type value_type; + typedef ht::hasher hasher; + typedef ht::key_equal key_equal; + typedef T data_type; + + typedef ht::size_type size_type; + typedef ht::difference_type difference_type; + typedef ht::pointer pointer; + typedef ht::const_pointer const_pointer; + typedef ht::reference reference; + typedef ht::const_reference const_reference; + + typedef ht::iterator iterator; + typedef ht::const_iterator const_iterator; + + hasher hash_funct() const { return rep.hash_funct(); } + key_equal key_eq() const { return rep.key_eq(); } + +public: + hash_multimap() : rep(100, hasher(), key_equal()) {} + explicit hash_multimap(size_type n) : rep(n, hasher(), key_equal()) {} + hash_multimap(size_type n, const hasher& hf) : rep(n, hf, key_equal()) {} + hash_multimap(size_type n, const hasher& hf, const key_equal& eql) + : rep(n, hf, eql) {} + +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + hash_multimap(InputIterator f, InputIterator l) + : rep(100, hasher(), key_equal()) { rep.insert_equal(f, l); } + template <class InputIterator> + hash_multimap(InputIterator f, InputIterator l, size_type n) + : rep(n, hasher(), key_equal()) { rep.insert_equal(f, l); } + template <class InputIterator> + hash_multimap(InputIterator f, InputIterator l, size_type n, + const hasher& hf) + : rep(n, hf, key_equal()) { rep.insert_equal(f, l); } + template <class InputIterator> + hash_multimap(InputIterator f, InputIterator l, size_type n, + const hasher& hf, const key_equal& eql) + : rep(n, hf, eql) { rep.insert_equal(f, l); } + +#else + hash_multimap(const value_type* f, const value_type* l) + : rep(100, hasher(), key_equal()) { rep.insert_equal(f, l); } + hash_multimap(const value_type* f, const value_type* l, size_type n) + : rep(n, hasher(), key_equal()) { rep.insert_equal(f, l); } + hash_multimap(const value_type* f, const value_type* l, size_type n, + const hasher& hf) + : rep(n, hf, key_equal()) { rep.insert_equal(f, l); } + hash_multimap(const value_type* f, const value_type* l, size_type n, + const hasher& hf, const key_equal& eql) + : rep(n, hf, eql) { rep.insert_equal(f, l); } + + hash_multimap(const_iterator f, const_iterator l) + : rep(100, hasher(), key_equal()) { rep.insert_equal(f, l); } + hash_multimap(const_iterator f, const_iterator l, size_type n) + : rep(n, hasher(), key_equal()) { rep.insert_equal(f, l); } + hash_multimap(const_iterator f, const_iterator l, size_type n, + const hasher& hf) + : rep(n, hf, key_equal()) { rep.insert_equal(f, l); } + hash_multimap(const_iterator f, const_iterator l, size_type n, + const hasher& hf, const key_equal& eql) + : rep(n, hf, eql) { rep.insert_equal(f, l); } +#endif /*__STL_MEMBER_TEMPLATES */ + +public: + size_type size() const { return rep.size(); } + size_type max_size() const { return rep.max_size(); } + bool empty() const { return rep.empty(); } + void swap(hash_multimap& hs) { rep.swap(hs.rep); } + friend bool operator==(const hash_multimap<Key,T,HashFcn,EqualKey,Alloc>&, + const hash_multimap<Key,T,HashFcn,EqualKey,Alloc>&); + + iterator begin() { return rep.begin(); } + iterator end() { return rep.end(); } + const_iterator begin() const { return rep.begin(); } + const_iterator end() const { return rep.end(); } + +public: + iterator insert(const value_type& obj) { return rep.insert_equal(obj); } +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + void insert(InputIterator f, InputIterator l) { rep.insert_equal(f,l); } +#else + void insert(const value_type* f, const value_type* l) { + rep.insert_equal(f,l); + } + void insert(const_iterator f, const_iterator l) { rep.insert_equal(f, l); } +#endif /*__STL_MEMBER_TEMPLATES */ + iterator insert_noresize(const value_type& obj) + { return rep.insert_equal_noresize(obj); } + + iterator find(const key_type& key) { return rep.find(key); } + const_iterator find(const key_type& key) const { return rep.find(key); } + + size_type count(const key_type& key) const { return rep.count(key); } + + pair<iterator, iterator> equal_range(const key_type& key) + { return rep.equal_range(key); } + pair<const_iterator, const_iterator> equal_range(const key_type& key) const + { return rep.equal_range(key); } + + size_type erase(const key_type& key) {return rep.erase(key); } + void erase(iterator it) { rep.erase(it); } + void erase(iterator f, iterator l) { rep.erase(f, l); } + void clear() { rep.clear(); } + +public: + void resize(size_type hint) { rep.resize(hint); } + size_type bucket_count() const { return rep.bucket_count(); } + size_type max_bucket_count() const { return rep.max_bucket_count(); } + size_type elems_in_bucket(size_type n) const + { return rep.elems_in_bucket(n); } +}; + +template <class Key, class T, class HF, class EqKey, class Alloc> +inline bool operator==(const hash_multimap<Key, T, HF, EqKey, Alloc>& hm1, + const hash_multimap<Key, T, HF, EqKey, Alloc>& hm2) +{ + return hm1.rep == hm2.rep; +} + +#endif /* __SGI_STL_HASH_MAP_H */ diff --git a/libstdc++/stl/hash_set.h b/libstdc++/stl/hash_set.h new file mode 100644 index 0000000..2c7125e --- /dev/null +++ b/libstdc++/stl/hash_set.h @@ -0,0 +1,306 @@ +/* + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef __SGI_STL_HASH_SET_H +#define __SGI_STL_HASH_SET_H + +#ifndef __SGI_STL_HASHTABLE_H +#include <hashtable.h> +#endif /* __SGI_STL_HASHTABLE_H */ + +#ifndef __STL_LIMITED_DEFAULT_TEMPLATES +template <class Value, class HashFcn = hash<Value>, + class EqualKey = equal_to<Value>, + class Alloc = alloc> +#else +template <class Value, class HashFcn, class EqualKey, class Alloc = alloc> +#endif +class hash_set +{ +private: + typedef hashtable<Value, Value, HashFcn, identity<Value>, + EqualKey, Alloc> ht; + ht rep; + +public: + typedef ht::key_type key_type; + typedef ht::value_type value_type; + typedef ht::hasher hasher; + typedef ht::key_equal key_equal; + + typedef ht::size_type size_type; + typedef ht::difference_type difference_type; + typedef ht::const_pointer pointer; + typedef ht::const_pointer const_pointer; + typedef ht::const_reference reference; + typedef ht::const_reference const_reference; + + typedef ht::const_iterator iterator; + typedef ht::const_iterator const_iterator; + + hasher hash_funct() const { return rep.hash_funct(); } + key_equal key_eq() const { return rep.key_eq(); } + +public: + hash_set() : rep(100, hasher(), key_equal()) {} + explicit hash_set(size_type n) : rep(n, hasher(), key_equal()) {} + hash_set(size_type n, const hasher& hf) : rep(n, hf, key_equal()) {} + hash_set(size_type n, const hasher& hf, const key_equal& eql) + : rep(n, hf, eql) {} + +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + hash_set(InputIterator f, InputIterator l) + : rep(100, hasher(), key_equal()) { rep.insert_unique(f, l); } + template <class InputIterator> + hash_set(InputIterator f, InputIterator l, size_type n) + : rep(n, hasher(), key_equal()) { rep.insert_unique(f, l); } + template <class InputIterator> + hash_set(InputIterator f, InputIterator l, size_type n, + const hasher& hf) + : rep(n, hf, key_equal()) { rep.insert_unique(f, l); } + template <class InputIterator> + hash_set(InputIterator f, InputIterator l, size_type n, + const hasher& hf, const key_equal& eql) + : rep(n, hf, eql) { rep.insert_unique(f, l); } +#else + + hash_set(const value_type* f, const value_type* l) + : rep(100, hasher(), key_equal()) { rep.insert_unique(f, l); } + hash_set(const value_type* f, const value_type* l, size_type n) + : rep(n, hasher(), key_equal()) { rep.insert_unique(f, l); } + hash_set(const value_type* f, const value_type* l, size_type n, + const hasher& hf) + : rep(n, hf, key_equal()) { rep.insert_unique(f, l); } + hash_set(const value_type* f, const value_type* l, size_type n, + const hasher& hf, const key_equal& eql) + : rep(n, hf, eql) { rep.insert_unique(f, l); } + + hash_set(const_iterator f, const_iterator l) + : rep(100, hasher(), key_equal()) { rep.insert_unique(f, l); } + hash_set(const_iterator f, const_iterator l, size_type n) + : rep(n, hasher(), key_equal()) { rep.insert_unique(f, l); } + hash_set(const_iterator f, const_iterator l, size_type n, + const hasher& hf) + : rep(n, hf, key_equal()) { rep.insert_unique(f, l); } + hash_set(const_iterator f, const_iterator l, size_type n, + const hasher& hf, const key_equal& eql) + : rep(n, hf, eql) { rep.insert_unique(f, l); } +#endif /*__STL_MEMBER_TEMPLATES */ + +public: + size_type size() const { return rep.size(); } + size_type max_size() const { return rep.max_size(); } + bool empty() const { return rep.empty(); } + void swap(hash_set& hs) { rep.swap(hs.rep); } + friend bool operator==(const hash_set<Value,HashFcn,EqualKey,Alloc>&, + const hash_set<Value,HashFcn,EqualKey,Alloc>&); + + iterator begin() const { return rep.begin(); } + iterator end() const { return rep.end(); } + +public: + pair<iterator, bool> insert(const value_type& obj) + { + pair<ht::iterator, bool> p = rep.insert_unique(obj); + return pair<iterator, bool>(p.first, p.second); + } +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + void insert(InputIterator f, InputIterator l) { rep.insert_unique(f,l); } +#else + void insert(const value_type* f, const value_type* l) { + rep.insert_unique(f,l); + } + void insert(const_iterator f, const_iterator l) {rep.insert_unique(f, l); } +#endif /*__STL_MEMBER_TEMPLATES */ + pair<iterator, bool> insert_noresize(const value_type& obj) + { + pair<ht::iterator, bool> p = rep.insert_unique_noresize(obj); + return pair<iterator, bool>(p.first, p.second); + } + + iterator find(const key_type& key) const { return rep.find(key); } + + size_type count(const key_type& key) const { return rep.count(key); } + + pair<iterator, iterator> equal_range(const key_type& key) const + { return rep.equal_range(key); } + + size_type erase(const key_type& key) {return rep.erase(key); } + void erase(iterator it) { rep.erase(it); } + void erase(iterator f, iterator l) { rep.erase(f, l); } + void clear() { rep.clear(); } + +public: + void resize(size_type hint) { rep.resize(hint); } + size_type bucket_count() const { return rep.bucket_count(); } + size_type max_bucket_count() const { return rep.max_bucket_count(); } + size_type elems_in_bucket(size_type n) const + { return rep.elems_in_bucket(n); } +}; + +template <class Value, class HashFcn, class EqualKey, class Alloc> +inline bool operator==(const hash_set<Value, HashFcn, EqualKey, Alloc>& hs1, + const hash_set<Value, HashFcn, EqualKey, Alloc>& hs2) +{ + return hs1.rep == hs2.rep; +} + +#ifndef __STL_LIMITED_DEFAULT_TEMPLATES +template <class Value, class HashFcn = hash<Value>, + class EqualKey = equal_to<Value>, + class Alloc = alloc> +#else +template <class Value, class HashFcn, class EqualKey, class Alloc = alloc> +#endif +class hash_multiset +{ +private: + typedef hashtable<Value, Value, HashFcn, identity<Value>, + EqualKey, Alloc> ht; + ht rep; + +public: + typedef ht::key_type key_type; + typedef ht::value_type value_type; + typedef ht::hasher hasher; + typedef ht::key_equal key_equal; + + typedef ht::size_type size_type; + typedef ht::difference_type difference_type; + typedef ht::const_pointer pointer; + typedef ht::const_pointer const_pointer; + typedef ht::const_reference reference; + typedef ht::const_reference const_reference; + + typedef ht::const_iterator iterator; + typedef ht::const_iterator const_iterator; + + hasher hash_funct() const { return rep.hash_funct(); } + key_equal key_eq() const { return rep.key_eq(); } + +public: + hash_multiset() : rep(100, hasher(), key_equal()) {} + explicit hash_multiset(size_type n) : rep(n, hasher(), key_equal()) {} + hash_multiset(size_type n, const hasher& hf) : rep(n, hf, key_equal()) {} + hash_multiset(size_type n, const hasher& hf, const key_equal& eql) + : rep(n, hf, eql) {} + +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + hash_multiset(InputIterator f, InputIterator l) + : rep(100, hasher(), key_equal()) { rep.insert_equal(f, l); } + template <class InputIterator> + hash_multiset(InputIterator f, InputIterator l, size_type n) + : rep(n, hasher(), key_equal()) { rep.insert_equal(f, l); } + template <class InputIterator> + hash_multiset(InputIterator f, InputIterator l, size_type n, + const hasher& hf) + : rep(n, hf, key_equal()) { rep.insert_equal(f, l); } + template <class InputIterator> + hash_multiset(InputIterator f, InputIterator l, size_type n, + const hasher& hf, const key_equal& eql) + : rep(n, hf, eql) { rep.insert_equal(f, l); } +#else + + hash_multiset(const value_type* f, const value_type* l) + : rep(100, hasher(), key_equal()) { rep.insert_equal(f, l); } + hash_multiset(const value_type* f, const value_type* l, size_type n) + : rep(n, hasher(), key_equal()) { rep.insert_equal(f, l); } + hash_multiset(const value_type* f, const value_type* l, size_type n, + const hasher& hf) + : rep(n, hf, key_equal()) { rep.insert_equal(f, l); } + hash_multiset(const value_type* f, const value_type* l, size_type n, + const hasher& hf, const key_equal& eql) + : rep(n, hf, eql) { rep.insert_equal(f, l); } + + hash_multiset(const_iterator f, const_iterator l) + : rep(100, hasher(), key_equal()) { rep.insert_equal(f, l); } + hash_multiset(const_iterator f, const_iterator l, size_type n) + : rep(n, hasher(), key_equal()) { rep.insert_equal(f, l); } + hash_multiset(const_iterator f, const_iterator l, size_type n, + const hasher& hf) + : rep(n, hf, key_equal()) { rep.insert_equal(f, l); } + hash_multiset(const_iterator f, const_iterator l, size_type n, + const hasher& hf, const key_equal& eql) + : rep(n, hf, eql) { rep.insert_equal(f, l); } +#endif /*__STL_MEMBER_TEMPLATES */ + +public: + size_type size() const { return rep.size(); } + size_type max_size() const { return rep.max_size(); } + bool empty() const { return rep.empty(); } + void swap(hash_multiset& hs) { rep.swap(hs.rep); } + friend bool operator==(const hash_multiset<Value,HashFcn,EqualKey,Alloc>&, + const hash_multiset<Value,HashFcn,EqualKey,Alloc>&); + + iterator begin() const { return rep.begin(); } + iterator end() const { return rep.end(); } + +public: + iterator insert(const value_type& obj) { return rep.insert_equal(obj); } +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + void insert(InputIterator f, InputIterator l) { rep.insert_equal(f,l); } +#else + void insert(const value_type* f, const value_type* l) { + rep.insert_equal(f,l); + } + void insert(const_iterator f, const_iterator l) { rep.insert_equal(f, l); } +#endif /*__STL_MEMBER_TEMPLATES */ + iterator insert_noresize(const value_type& obj) + { return rep.insert_equal_noresize(obj); } + + iterator find(const key_type& key) const { return rep.find(key); } + + size_type count(const key_type& key) const { return rep.count(key); } + + pair<iterator, iterator> equal_range(const key_type& key) const + { return rep.equal_range(key); } + + size_type erase(const key_type& key) {return rep.erase(key); } + void erase(iterator it) { rep.erase(it); } + void erase(iterator f, iterator l) { rep.erase(f, l); } + void clear() { rep.clear(); } + +public: + void resize(size_type hint) { rep.resize(hint); } + size_type bucket_count() const { return rep.bucket_count(); } + size_type max_bucket_count() const { return rep.max_bucket_count(); } + size_type elems_in_bucket(size_type n) const + { return rep.elems_in_bucket(n); } +}; + +template <class Val, class HashFcn, class EqualKey, class Alloc> +inline bool operator==(const hash_multiset<Val, HashFcn, EqualKey, Alloc>& hs1, + const hash_multiset<Val, HashFcn, EqualKey, Alloc>& hs2) +{ + return hs1.rep == hs2.rep; +} + + +#endif /* __SGI_STL_HASH_SET_H */ diff --git a/libstdc++/stl/hashtable.h b/libstdc++/stl/hashtable.h new file mode 100644 index 0000000..420d7a8 --- /dev/null +++ b/libstdc++/stl/hashtable.h @@ -0,0 +1,1013 @@ +/* + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef __SGI_STL_HASHTABLE_H +#define __SGI_STL_HASHTABLE_H + +// Hashtable class, used to implement the hashed associative containers +// hash_set, hash_map, hash_multiset, and hash_multimap. + + +#include <stdlib.h> +#include <stddef.h> +#include <algo.h> +#include <vector.h> + + +template <class Key> struct hash { }; + +inline size_t __stl_hash_string(const char* s) +{ + unsigned long h = 0; + for ( ; *s; ++s) + h = 5*h + *s; + + return size_t(h); +} + +struct hash<char*> +{ + size_t operator()(const char* s) const { return __stl_hash_string(s); } +}; + +struct hash<const char*> +{ + size_t operator()(const char* s) const { return __stl_hash_string(s); } +}; + +struct hash<char> { + size_t operator()(char x) const { return x; } +}; +struct hash<unsigned char> { + size_t operator()(unsigned char x) const { return x; } +}; +struct hash<signed char> { + size_t operator()(unsigned char x) const { return x; } +}; +struct hash<short> { + size_t operator()(short x) const { return x; } +}; +struct hash<unsigned short> { + size_t operator()(unsigned short x) const { return x; } +}; +struct hash<int> { + size_t operator()(int x) const { return x; } +}; +struct hash<unsigned int> { + size_t operator()(unsigned int x) const { return x; } +}; +struct hash<long> { + size_t operator()(long x) const { return x; } +}; +struct hash<unsigned long> { + size_t operator()(unsigned long x) const { return x; } +}; + +template <class Value> +struct __hashtable_node +{ + __hashtable_node* next; + Value val; +}; + +template <class Value, class Key, class HashFcn, + class ExtractKey, class EqualKey, class Alloc = alloc> +class hashtable; + +template <class Value, class Key, class HashFcn, + class ExtractKey, class EqualKey, class Alloc> +struct __hashtable_iterator; + +template <class Value, class Key, class HashFcn, + class ExtractKey, class EqualKey, class Alloc> +struct __hashtable_const_iterator; + +template <class Value, class Key, class HashFcn, + class ExtractKey, class EqualKey, class Alloc> +struct __hashtable_iterator { + typedef hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc> + hashtable; + typedef __hashtable_iterator<Value, Key, HashFcn, + ExtractKey, EqualKey, Alloc> + iterator; + typedef __hashtable_const_iterator<Value, Key, HashFcn, + ExtractKey, EqualKey, Alloc> + const_iterator; + typedef __hashtable_node<Value> node; + + typedef forward_iterator_tag iterator_category; + typedef Value value_type; + typedef ptrdiff_t difference_type; + typedef size_t size_type; + typedef Value& reference; + typedef const Value& const_reference; + typedef Value* pointer; + + node* cur; + hashtable* ht; + + __hashtable_iterator(node* n, hashtable* tab) : cur(n), ht(tab) {} + __hashtable_iterator() {} + reference operator*() const { return cur->val; } + iterator& operator++(); + iterator operator++(int); + bool operator==(const iterator& it) const { return cur == it.cur; } + bool operator!=(const iterator& it) const { return cur != it.cur; } +}; + + +template <class Value, class Key, class HashFcn, + class ExtractKey, class EqualKey, class Alloc> +struct __hashtable_const_iterator { + typedef hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc> + hashtable; + typedef __hashtable_iterator<Value, Key, HashFcn, + ExtractKey, EqualKey, Alloc> + iterator; + typedef __hashtable_const_iterator<Value, Key, HashFcn, + ExtractKey, EqualKey, Alloc> + const_iterator; + typedef __hashtable_node<Value> node; + + typedef forward_iterator_tag iterator_category; + typedef Value value_type; + typedef ptrdiff_t difference_type; + typedef size_t size_type; + typedef Value& reference; + typedef const Value& const_reference; + typedef Value* pointer; + + const node* cur; + const hashtable* ht; + + __hashtable_const_iterator(const node* n, const hashtable* tab) + : cur(n), ht(tab) {} + __hashtable_const_iterator() {} + __hashtable_const_iterator(const iterator& it) : cur(it.cur), ht(it.ht) {} + const_reference operator*() const { return cur->val; } + const_iterator& operator++(); + const_iterator operator++(int); + bool operator==(const const_iterator& it) const { return cur == it.cur; } + bool operator!=(const const_iterator& it) const { return cur != it.cur; } +}; + +// Note: assumes long is at least 32 bits. +static const int __stl_num_primes = 28; +static const unsigned long __stl_prime_list[__stl_num_primes] = +{ + 53, 97, 193, 389, 769, + 1543, 3079, 6151, 12289, 24593, + 49157, 98317, 196613, 393241, 786433, + 1572869, 3145739, 6291469, 12582917, 25165843, + 50331653, 100663319, 201326611, 402653189, 805306457, + 1610612741, 3221225473, 4294967291 +}; + +inline unsigned long __stl_next_prime(unsigned long n) +{ + const unsigned long* first = __stl_prime_list; + const unsigned long* last = __stl_prime_list + __stl_num_primes; + const unsigned long* pos = lower_bound(first, last, n); + return pos == last ? *(last - 1) : *pos; +} + + +template <class Value, class Key, class HashFcn, + class ExtractKey, class EqualKey, + class Alloc> +class hashtable { +public: + typedef Key key_type; + typedef Value value_type; + typedef HashFcn hasher; + typedef EqualKey key_equal; + + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + hasher hash_funct() const { return hash; } + key_equal key_eq() const { return equals; } + +private: + hasher hash; + key_equal equals; + ExtractKey get_key; + + typedef __hashtable_node<Value> node; + typedef simple_alloc<node, Alloc> node_allocator; + + vector<node*,Alloc> buckets; + size_type num_elements; + +public: + typedef __hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, + Alloc> + iterator; + + typedef __hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, + Alloc> + const_iterator; + + friend struct + __hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>; + friend struct + __hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>; + +public: + hashtable(size_type n, + const HashFcn& hf, + const EqualKey& eql, + const ExtractKey& ext) + : hash(hf), equals(eql), get_key(ext), num_elements(0) + { + initialize_buckets(n); + } + + hashtable(size_type n, + const HashFcn& hf, + const EqualKey& eql) + : hash(hf), equals(eql), get_key(ExtractKey()), num_elements(0) + { + initialize_buckets(n); + } + + hashtable(const hashtable& ht) + : hash(ht.hash), equals(ht.equals), get_key(ht.get_key), num_elements(0) + { + copy_from(ht); + } + + hashtable& operator= (const hashtable& ht) + { + if (&ht != this) { + clear(); + hash = ht.hash; + equals = ht.equals; + get_key = ht.get_key; + copy_from(ht); + } + return *this; + } + + ~hashtable() { clear(); } + + size_type size() const { return num_elements; } + size_type max_size() const { return size_type(-1); } + bool empty() const { return size() == 0; } + + void swap(hashtable& ht) + { + ::swap(hash, ht.hash); + ::swap(equals, ht.equals); + ::swap(get_key, ht.get_key); + buckets.swap(ht.buckets); + ::swap(num_elements, ht.num_elements); + } + + iterator begin() + { + for (size_type n = 0; n < buckets.size(); ++n) + if (buckets[n]) + return iterator(buckets[n], this); + return end(); + } + + iterator end() { return iterator(0, this); } + + const_iterator begin() const + { + for (size_type n = 0; n < buckets.size(); ++n) + if (buckets[n]) + return const_iterator(buckets[n], this); + return end(); + } + + const_iterator end() const { return const_iterator(0, this); } + + friend bool operator== (const hashtable<Value, Key, + HashFcn, ExtractKey, EqualKey, + Alloc>&, + const hashtable<Value, Key, + HashFcn, ExtractKey, EqualKey, + Alloc>&); + +public: + + size_type bucket_count() const { return buckets.size(); } + + size_type max_bucket_count() const + { return __stl_prime_list[__stl_num_primes - 1]; } + + size_type elems_in_bucket(size_type bucket) const + { + size_type result = 0; + for (node* cur = buckets[bucket]; cur; cur = cur->next) + result += 1; + return result; + } + + pair<iterator, bool> insert_unique(const value_type& obj) + { + resize(num_elements + 1); + return insert_unique_noresize(obj); + } + + iterator insert_equal(const value_type& obj) + { + resize(num_elements + 1); + return insert_equal_noresize(obj); + } + + pair<iterator, bool> insert_unique_noresize(const value_type& obj); + iterator insert_equal_noresize(const value_type& obj); + +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + void insert_unique(InputIterator f, InputIterator l) + { + insert_unique(f, l, iterator_category(f)); + } + + template <class InputIterator> + void insert_equal(InputIterator f, InputIterator l) + { + insert_equal(f, l, iterator_category(f)); + } + + template <class InputIterator> + void insert_unique(InputIterator f, InputIterator l, + input_iterator_tag) + { + for ( ; f != l; ++f) + insert_unique(*f); + } + + template <class InputIterator> + void insert_equal(InputIterator f, InputIterator l, + input_iterator_tag) + { + for ( ; f != l; ++f) + insert_equal(*f); + } + + template <class ForwardIterator> + void insert_unique(ForwardIterator f, ForwardIterator l, + forward_iterator_tag) + { + size_type n = 0; + distance(f, l, n); + resize(num_elements + n); + for ( ; n > 0; --n, ++f) + insert_unique_noresize(*f); + } + + template <class ForwardIterator> + void insert_equal(ForwardIterator f, ForwardIterator l, + forward_iterator_tag) + { + size_type n = 0; + distance(f, l, n); + resize(num_elements + n); + for ( ; n > 0; --n, ++f) + insert_equal_noresize(*f); + } + + template <class BidirectionalIterator> + void insert_unique(BidirectionalIterator f, BidirectionalIterator l, + bidirectional_iterator_tag) + { + insert_unique(f, l, forward_iterator_tag()); + } + + template <class BidirectionalIterator> + void insert_equal(BidirectionalIterator f, BidirectionalIterator l, + bidirectional_iterator_tag) + { + insert_equal(f, l, forward_iterator_tag()); + } + + template <class RandomAccessIterator> + void insert_unique(RandomAccessIterator f, RandomAccessIterator l, + random_access_iterator_tag) + { + insert_unique(f, l, forward_iterator_tag()); + } + + template <class RandomAccessIterator> + void insert_equal(RandomAccessIterator f, RandomAccessIterator l, + random_access_iterator_tag) + { + insert_equal(f, l, forward_iterator_tag()); + } + +#else /* __STL_MEMBER_TEMPLATES */ + void insert_unique(const value_type* f, const value_type* l) + { + size_type n = l - f; + resize(num_elements + n); + for ( ; n > 0; --n, ++f) + insert_unique_noresize(*f); + } + + void insert_equal(const value_type* f, const value_type* l) + { + size_type n = l - f; + resize(num_elements + n); + for ( ; n > 0; --n, ++f) + insert_equal_noresize(*f); + } + + void insert_unique(const_iterator f, const_iterator l) + { + size_type n = 0; + distance(f, l, n); + resize(num_elements + n); + for ( ; n > 0; --n, ++f) + insert_unique_noresize(*f); + } + + void insert_equal(const_iterator f, const_iterator l) + { + size_type n = 0; + distance(f, l, n); + resize(num_elements + n); + for ( ; n > 0; --n, ++f) + insert_equal_noresize(*f); + } +#endif /*__STL_MEMBER_TEMPLATES */ + + reference find_or_insert(const value_type& obj); + + iterator find(const key_type& key) + { + size_type n = bkt_num_key(key); + node* first; + for ( first = buckets[n]; + first && !equals(get_key(first->val), key); + first = first->next) + {} + return iterator(first, this); + } + + const_iterator find(const key_type& key) const + { + size_type n = bkt_num_key(key); + const node* first; + for ( first = buckets[n]; + first && !equals(get_key(first->val), key); + first = first->next) + {} + return const_iterator(first, this); + } + + size_type count(const key_type& key) const + { + const size_type n = bkt_num_key(key); + size_type result = 0; + + for (const node* cur = buckets[n]; cur; cur = cur->next) + if (equals(get_key(cur->val), key)) + ++result; + return result; + } + + pair<iterator, iterator> equal_range(const key_type& key); + pair<const_iterator, const_iterator> equal_range(const key_type& key) const; + + size_type erase(const key_type& key); + void erase(const iterator& it); + void erase(iterator first, iterator last); + + void erase(const const_iterator& it); + void erase(const_iterator first, const_iterator last); + + void resize(size_type num_elements_hint); + void clear(); + +private: + size_type next_size(size_type n) const { return __stl_next_prime(n); } + + void initialize_buckets(size_type n) + { + const size_type n_buckets = next_size(n); + buckets.reserve(n_buckets); + buckets.insert(buckets.end(), n_buckets, (node*) 0); + num_elements = 0; + } + + size_type bkt_num_key(const key_type& key) const + { + return bkt_num_key(key, buckets.size()); + } + + size_type bkt_num(const value_type& obj) const + { + return bkt_num_key(get_key(obj)); + } + + size_type bkt_num_key(const key_type& key, size_t n) const + { + return hash(key) % n; + } + + size_type bkt_num(const value_type& obj, size_t n) const + { + return bkt_num_key(get_key(obj), n); + } + + node* new_node(const value_type& obj) + { + node* n = node_allocator::allocate(); + n->next = 0; +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + construct(&n->val, obj); + return n; +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + node_allocator::deallocate(n); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } + + void delete_node(node* n) + { + destroy(&n->val); + node_allocator::deallocate(n); + } + + void erase_bucket(const size_type n, node* first, node* last); + void erase_bucket(const size_type n, node* last); + + void copy_from(const hashtable& ht); + +}; + +template <class V, class K, class HF, class ExK, class EqK, class A> +__hashtable_iterator<V, K, HF, ExK, EqK, A>& +__hashtable_iterator<V, K, HF, ExK, EqK, A>::operator++() +{ + const node* old = cur; + cur = cur->next; + if (!cur) { + size_type bucket = ht->bkt_num(old->val); + while (!cur && ++bucket < ht->buckets.size()) + cur = ht->buckets[bucket]; + } + return *this; +} + +template <class V, class K, class HF, class ExK, class EqK, class A> +inline __hashtable_iterator<V, K, HF, ExK, EqK, A> +__hashtable_iterator<V, K, HF, ExK, EqK, A>::operator++(int) +{ + iterator tmp = *this; + ++*this; + return tmp; +} + +template <class V, class K, class HF, class ExK, class EqK, class A> +__hashtable_const_iterator<V, K, HF, ExK, EqK, A>& +__hashtable_const_iterator<V, K, HF, ExK, EqK, A>::operator++() +{ + const node* old = cur; + cur = cur->next; + if (!cur) { + size_type bucket = ht->bkt_num(old->val); + while (!cur && ++bucket < ht->buckets.size()) + cur = ht->buckets[bucket]; + } + return *this; +} + +template <class V, class K, class HF, class ExK, class EqK, class A> +inline __hashtable_const_iterator<V, K, HF, ExK, EqK, A> +__hashtable_const_iterator<V, K, HF, ExK, EqK, A>::operator++(int) +{ + const_iterator tmp = *this; + ++*this; + return tmp; +} + + +template <class V, class K, class HF, class ExK, class EqK, class All> +inline forward_iterator_tag +iterator_category(const __hashtable_iterator<V, K, HF, ExK, EqK, All>&) +{ + return forward_iterator_tag(); +} + +template <class V, class K, class HF, class ExK, class EqK, class All> +inline V* value_type(const __hashtable_iterator<V, K, HF, ExK, EqK, All>&) +{ + return (V*) 0; +} + +template <class V, class K, class HF, class ExK, class EqK, class All> +inline hashtable<V, K, HF, ExK, EqK, All>::difference_type* +distance_type(const __hashtable_iterator<V, K, HF, ExK, EqK, All>&) +{ + return (hashtable<V, K, HF, ExK, EqK, All>::difference_type*) 0; +} + +template <class V, class K, class HF, class ExK, class EqK, class All> +inline forward_iterator_tag +iterator_category(const __hashtable_const_iterator<V, K, HF, ExK, EqK, All>&) +{ + return forward_iterator_tag(); +} + +template <class V, class K, class HF, class ExK, class EqK, class All> +inline V* +value_type(const __hashtable_const_iterator<V, K, HF, ExK, EqK, All>&) +{ + return (V*) 0; +} + +template <class V, class K, class HF, class ExK, class EqK, class All> +inline hashtable<V, K, HF, ExK, EqK, All>::difference_type* +distance_type(const __hashtable_const_iterator<V, K, HF, ExK, EqK, All>&) +{ + return (hashtable<V, K, HF, ExK, EqK, All>::difference_type*) 0; +} + +template <class V, class K, class HF, class Ex, class Eq, class A> +bool operator==(const hashtable<V, K, HF, Ex, Eq, A>& ht1, + const hashtable<V, K, HF, Ex, Eq, A>& ht2) +{ + typedef hashtable<V, K, HF, Ex, Eq, A>::node node; + if (ht1.buckets.size() != ht2.buckets.size()) + return false; + for (int n = 0; n < ht1.buckets.size(); ++n) { + node* cur1 = ht1.buckets[n]; + node* cur2 = ht2.buckets[n]; + for ( ; cur1 && cur2 && cur1->val == cur2->val; + cur1 = cur1->next, cur2 = cur2->next) + {} + if (cur1 || cur2) + return false; + } + return true; +} + +template <class V, class K, class HF, class Ex, class Eq, class A> +pair<hashtable<V, K, HF, Ex, Eq, A>::iterator, bool> +hashtable<V, K, HF, Ex, Eq, A>::insert_unique_noresize(const value_type& obj) +{ + const size_type n = bkt_num(obj); + node* first = buckets[n]; + + for (node* cur = first; cur; cur = cur->next) + if (equals(get_key(cur->val), get_key(obj))) + return pair<iterator, bool>(iterator(cur, this), false); + + node* tmp = new_node(obj); + tmp->next = first; + buckets[n] = tmp; + ++num_elements; + return pair<iterator, bool>(iterator(tmp, this), true); +} + +template <class V, class K, class HF, class Ex, class Eq, class A> +hashtable<V, K, HF, Ex, Eq, A>::iterator +hashtable<V, K, HF, Ex, Eq, A>::insert_equal_noresize(const value_type& obj) +{ + const size_type n = bkt_num(obj); + node* first = buckets[n]; + + for (node* cur = first; cur; cur = cur->next) + if (equals(get_key(cur->val), get_key(obj))) { + node* tmp = new_node(obj); + tmp->next = cur->next; + cur->next = tmp; + ++num_elements; + return iterator(tmp, this); + } + + node* tmp = new_node(obj); + tmp->next = first; + buckets[n] = tmp; + ++num_elements; + return iterator(tmp, this); +} + +template <class V, class K, class HF, class Ex, class Eq, class A> +hashtable<V, K, HF, Ex, Eq, A>::reference +hashtable<V, K, HF, Ex, Eq, A>::find_or_insert(const value_type& obj) +{ + resize(num_elements + 1); + + size_type n = bkt_num(obj); + node* first = buckets[n]; + + for (node* cur = first; cur; cur = cur->next) + if (equals(get_key(cur->val), get_key(obj))) + return cur->val; + + node* tmp = new_node(obj); + tmp->next = first; + buckets[n] = tmp; + ++num_elements; + return tmp->val; +} + +template <class V, class K, class HF, class Ex, class Eq, class A> +pair<hashtable<V, K, HF, Ex, Eq, A>::iterator, + hashtable<V, K, HF, Ex, Eq, A>::iterator> +hashtable<V, K, HF, Ex, Eq, A>::equal_range(const key_type& key) +{ + typedef pair<iterator, iterator> pii; + const size_type n = bkt_num_key(key); + + for (node* first = buckets[n]; first; first = first->next) { + if (equals(get_key(first->val), key)) { + for (node* cur = first->next; cur; cur = cur->next) + if (!equals(get_key(cur->val), key)) + return pii(iterator(first, this), iterator(cur, this)); + for (size_type m = n + 1; m < buckets.size(); ++m) + if (buckets[m]) + return pii(iterator(first, this), + iterator(buckets[m], this)); + return pii(iterator(first, this), end()); + } + } + return pii(end(), end()); +} + +template <class V, class K, class HF, class Ex, class Eq, class A> +pair<hashtable<V, K, HF, Ex, Eq, A>::const_iterator, + hashtable<V, K, HF, Ex, Eq, A>::const_iterator> +hashtable<V, K, HF, Ex, Eq, A>::equal_range(const key_type& key) const +{ + typedef pair<const_iterator, const_iterator> pii; + const size_type n = bkt_num_key(key); + + for (const node* first = buckets[n] ; first; first = first->next) { + if (equals(get_key(first->val), key)) { + for (const node* cur = first->next; cur; cur = cur->next) + if (!equals(get_key(cur->val), key)) + return pii(const_iterator(first, this), + const_iterator(cur, this)); + for (size_type m = n + 1; m < buckets.size(); ++m) + if (buckets[m]) + return pii(const_iterator(first, this), + const_iterator(buckets[m], this)); + return pii(const_iterator(first, this), end()); + } + } + return pii(end(), end()); +} + +template <class V, class K, class HF, class Ex, class Eq, class A> +hashtable<V, K, HF, Ex, Eq, A>::size_type +hashtable<V, K, HF, Ex, Eq, A>::erase(const key_type& key) +{ + const size_type n = bkt_num_key(key); + node* first = buckets[n]; + size_type erased = 0; + + if (first) { + node* cur = first; + node* next = cur->next; + while (next) { + if (equals(get_key(next->val), key)) { + cur->next = next->next; + delete_node(next); + next = cur->next; + ++erased; + --num_elements; + } + else { + cur = next; + next = cur->next; + } + } + if (equals(get_key(first->val), key)) { + buckets[n] = first->next; + delete_node(first); + ++erased; + --num_elements; + } + } + return erased; +} + +template <class V, class K, class HF, class Ex, class Eq, class A> +void hashtable<V, K, HF, Ex, Eq, A>::erase(const iterator& it) +{ + if (node* const p = it.cur) { + const size_type n = bkt_num(p->val); + node* cur = buckets[n]; + + if (cur == p) { + buckets[n] = cur->next; + delete_node(cur); + --num_elements; + } + else { + node* next = cur->next; + while (next) { + if (next == p) { + cur->next = next->next; + delete_node(next); + --num_elements; + break; + } + else { + cur = next; + next = cur->next; + } + } + } + } +} + +template <class V, class K, class HF, class Ex, class Eq, class A> +void hashtable<V, K, HF, Ex, Eq, A>::erase(iterator first, iterator last) +{ + size_type f_bucket = first.cur ? bkt_num(first.cur->val) : buckets.size(); + size_type l_bucket = last.cur ? bkt_num(last.cur->val) : buckets.size(); + + if (first.cur == last.cur) + return; + else if (f_bucket == l_bucket) + erase_bucket(f_bucket, first.cur, last.cur); + else { + erase_bucket(f_bucket, first.cur, 0); + for (size_type n = f_bucket + 1; n < l_bucket; ++n) + erase_bucket(n, 0); + if (l_bucket != buckets.size()) + erase_bucket(l_bucket, last.cur); + } +} + +template <class V, class K, class HF, class Ex, class Eq, class A> +inline void +hashtable<V, K, HF, Ex, Eq, A>::erase(const_iterator first, + const_iterator last) +{ + erase(iterator(const_cast<hashtable::node*>(first.cur), + const_cast<hashtable*>(first.ht)), + iterator(const_cast<hashtable::node*>(last.cur), + const_cast<hashtable*>(last.ht))); +} + +template <class V, class K, class HF, class Ex, class Eq, class A> +inline void +hashtable<V, K, HF, Ex, Eq, A>::erase(const const_iterator& it) +{ + erase(iterator(const_cast<hashtable::node*>(it.cur), + const_cast<hashtable*>(it.ht))); +} + +template <class V, class K, class HF, class Ex, class Eq, class A> +void hashtable<V, K, HF, Ex, Eq, A>::resize(size_type num_elements_hint) +{ + const size_type old_n = buckets.size(); + if (num_elements_hint > old_n) { + const size_type n = next_size(num_elements_hint); + if (n > old_n) { + vector<node*, A> tmp(n, (node*) 0); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + for (size_type bucket = 0; bucket < old_n; ++bucket) { + node* first = buckets[bucket]; + while (first) { + size_type new_bucket = bkt_num(first->val, n); + buckets[bucket] = first->next; + first->next = tmp[new_bucket]; + tmp[new_bucket] = first; + first = buckets[bucket]; + } + } + buckets.swap(tmp); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + for (size_type bucket = 0; bucket < tmp.size(); ++bucket) { + while (tmp[bucket]) { + node* next = tmp[bucket]->next; + delete_node(tmp[bucket]); + tmp[bucket] = next; + } + } + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } + } +} + +template <class V, class K, class HF, class Ex, class Eq, class A> +void hashtable<V, K, HF, Ex, Eq, A>::erase_bucket(const size_type n, + node* first, node* last) +{ + node* cur = buckets[n]; + if (cur == first) + erase_bucket(n, last); + else { + node* next; + for (next = cur->next; next != first; cur = next, next = cur->next) + ; + while (next) { + cur->next = next->next; + delete_node(next); + next = cur->next; + --num_elements; + } + } +} + +template <class V, class K, class HF, class Ex, class Eq, class A> +void +hashtable<V, K, HF, Ex, Eq, A>::erase_bucket(const size_type n, node* last) +{ + node* cur = buckets[n]; + while (cur != last) { + node* next = cur->next; + delete_node(cur); + cur = next; + buckets[n] = cur; + --num_elements; + } +} + +template <class V, class K, class HF, class Ex, class Eq, class A> +void hashtable<V, K, HF, Ex, Eq, A>::clear() +{ + for (size_type i = 0; i < buckets.size(); ++i) { + node* cur = buckets[i]; + while (cur != 0) { + node* next = cur->next; + delete_node(cur); + cur = next; + } + buckets[i] = 0; + } + num_elements = 0; +} + + +template <class V, class K, class HF, class Ex, class Eq, class A> +void hashtable<V, K, HF, Ex, Eq, A>::copy_from(const hashtable& ht) +{ + buckets.clear(); + buckets.reserve(ht.buckets.size()); + buckets.insert(buckets.end(), ht.buckets.size(), (node*) 0); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + for (size_type i = 0; i < ht.buckets.size(); ++i) { + if (const node* cur = ht.buckets[i]) { + node* copy = new_node(cur->val); + buckets[i] = copy; + + for (node* next = cur->next; next; cur = next, next = cur->next) { + copy->next = new_node(next->val); + copy = copy->next; + } + } + } + num_elements = ht.num_elements; +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + clear(); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ +} + + +#endif /* __SGI_STL_HASHTABLE_H */ diff --git a/libstdc++/stl/heap.h b/libstdc++/stl/heap.h new file mode 100644 index 0000000..b24afaf --- /dev/null +++ b/libstdc++/stl/heap.h @@ -0,0 +1,204 @@ +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef __SGI_STL_HEAP_H +#define __SGI_STL_HEAP_H + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma set woff 1209 +#endif + +template <class RandomAccessIterator, class Distance, class T> +void __push_heap(RandomAccessIterator first, Distance holeIndex, + Distance topIndex, T value) { + Distance parent = (holeIndex - 1) / 2; + while (holeIndex > topIndex && *(first + parent) < value) { + *(first + holeIndex) = *(first + parent); + holeIndex = parent; + parent = (holeIndex - 1) / 2; + } + *(first + holeIndex) = value; +} + +template <class RandomAccessIterator, class Distance, class T> +inline void __push_heap_aux(RandomAccessIterator first, + RandomAccessIterator last, Distance*, T*) { + __push_heap(first, Distance((last - first) - 1), Distance(0), + T(*(last - 1))); +} + +template <class RandomAccessIterator> +inline void push_heap(RandomAccessIterator first, RandomAccessIterator last) { + __push_heap_aux(first, last, distance_type(first), value_type(first)); +} + +template <class RandomAccessIterator, class Distance, class T, class Compare> +void __push_heap(RandomAccessIterator first, Distance holeIndex, + Distance topIndex, T value, Compare comp) { + Distance parent = (holeIndex - 1) / 2; + while (holeIndex > topIndex && comp(*(first + parent), value)) { + *(first + holeIndex) = *(first + parent); + holeIndex = parent; + parent = (holeIndex - 1) / 2; + } + *(first + holeIndex) = value; +} + +template <class RandomAccessIterator, class Compare, class Distance, class T> +inline void __push_heap_aux(RandomAccessIterator first, + RandomAccessIterator last, Compare comp, + Distance*, T*) { + __push_heap(first, Distance((last - first) - 1), Distance(0), + T(*(last - 1)), comp); +} + +template <class RandomAccessIterator, class Compare> +inline void push_heap(RandomAccessIterator first, RandomAccessIterator last, + Compare comp) { + __push_heap_aux(first, last, comp, distance_type(first), value_type(first)); +} + +template <class RandomAccessIterator, class Distance, class T> +void __adjust_heap(RandomAccessIterator first, Distance holeIndex, + Distance len, T value) { + Distance topIndex = holeIndex; + Distance secondChild = 2 * holeIndex + 2; + while (secondChild < len) { + if (*(first + secondChild) < *(first + (secondChild - 1))) + secondChild--; + *(first + holeIndex) = *(first + secondChild); + holeIndex = secondChild; + secondChild = 2 * (secondChild + 1); + } + if (secondChild == len) { + *(first + holeIndex) = *(first + (secondChild - 1)); + holeIndex = secondChild - 1; + } + __push_heap(first, holeIndex, topIndex, value); +} + +template <class RandomAccessIterator, class T, class Distance> +inline void __pop_heap(RandomAccessIterator first, RandomAccessIterator last, + RandomAccessIterator result, T value, Distance*) { + *result = *first; + __adjust_heap(first, Distance(0), Distance(last - first), value); +} + +template <class RandomAccessIterator, class T> +inline void __pop_heap_aux(RandomAccessIterator first, + RandomAccessIterator last, T*) { + __pop_heap(first, last - 1, last - 1, T(*(last - 1)), distance_type(first)); +} + +template <class RandomAccessIterator> +inline void pop_heap(RandomAccessIterator first, RandomAccessIterator last) { + __pop_heap_aux(first, last, value_type(first)); +} + +template <class RandomAccessIterator, class Distance, class T, class Compare> +void __adjust_heap(RandomAccessIterator first, Distance holeIndex, + Distance len, T value, Compare comp) { + Distance topIndex = holeIndex; + Distance secondChild = 2 * holeIndex + 2; + while (secondChild < len) { + if (comp(*(first + secondChild), *(first + (secondChild - 1)))) + secondChild--; + *(first + holeIndex) = *(first + secondChild); + holeIndex = secondChild; + secondChild = 2 * (secondChild + 1); + } + if (secondChild == len) { + *(first + holeIndex) = *(first + (secondChild - 1)); + holeIndex = secondChild - 1; + } + __push_heap(first, holeIndex, topIndex, value, comp); +} + +template <class RandomAccessIterator, class T, class Compare, class Distance> +inline void __pop_heap(RandomAccessIterator first, RandomAccessIterator last, + RandomAccessIterator result, T value, Compare comp, + Distance*) { + *result = *first; + __adjust_heap(first, Distance(0), Distance(last - first), value, comp); +} + +template <class RandomAccessIterator, class T, class Compare> +inline void __pop_heap_aux(RandomAccessIterator first, + RandomAccessIterator last, T*, Compare comp) { + __pop_heap(first, last - 1, last - 1, T(*(last - 1)), comp, + distance_type(first)); +} + +template <class RandomAccessIterator, class Compare> +inline void pop_heap(RandomAccessIterator first, RandomAccessIterator last, + Compare comp) { + __pop_heap_aux(first, last, value_type(first), comp); +} + +template <class RandomAccessIterator, class T, class Distance> +void __make_heap(RandomAccessIterator first, RandomAccessIterator last, T*, + Distance*) { + if (last - first < 2) return; + Distance len = last - first; + Distance parent = (len - 2)/2; + + while (true) { + __adjust_heap(first, parent, len, T(*(first + parent))); + if (parent == 0) return; + parent--; + } +} + +template <class RandomAccessIterator> +inline void make_heap(RandomAccessIterator first, RandomAccessIterator last) { + __make_heap(first, last, value_type(first), distance_type(first)); +} + +template <class RandomAccessIterator, class Compare, class T, class Distance> +void __make_heap(RandomAccessIterator first, RandomAccessIterator last, + Compare comp, T*, Distance*) { + if (last - first < 2) return; + Distance len = last - first; + Distance parent = (len - 2)/2; + + while (true) { + __adjust_heap(first, parent, len, T(*(first + parent)), comp); + if (parent == 0) return; + parent--; + } +} + +template <class RandomAccessIterator, class Compare> +inline void make_heap(RandomAccessIterator first, RandomAccessIterator last, + Compare comp) { + __make_heap(first, last, comp, value_type(first), distance_type(first)); +} + +template <class RandomAccessIterator> +void sort_heap(RandomAccessIterator first, RandomAccessIterator last) { + while (last - first > 1) pop_heap(first, last--); +} + +template <class RandomAccessIterator, class Compare> +void sort_heap(RandomAccessIterator first, RandomAccessIterator last, + Compare comp) { + while (last - first > 1) pop_heap(first, last--, comp); +} + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma reset woff 1209 +#endif + +#endif /* __SGI_STL_HEAP_H */ diff --git a/libstdc++/stl/iterator.h b/libstdc++/stl/iterator.h new file mode 100644 index 0000000..bdd2260 --- /dev/null +++ b/libstdc++/stl/iterator.h @@ -0,0 +1,598 @@ +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#ifndef __SGI_STL_ITERATOR_H +#define __SGI_STL_ITERATOR_H + +#include <stddef.h> +#include <iostream.h> +#include <function.h> + +struct input_iterator_tag {}; +struct output_iterator_tag {}; +struct forward_iterator_tag {}; +struct bidirectional_iterator_tag {}; +struct random_access_iterator_tag {}; + +template <class T, class Distance> struct input_iterator { + typedef input_iterator_tag iterator_category; + typedef T value_type; + typedef Distance difference_type; + typedef T* pointer; + typedef T& reference; +}; + +struct output_iterator { + typedef output_iterator_tag iterator_category; +}; + +template <class T, class Distance> struct forward_iterator { + typedef forward_iterator_tag iterator_category; + typedef T value_type; + typedef Distance difference_type; + typedef T* pointer; + typedef T& reference; +}; + + +template <class T, class Distance> struct bidirectional_iterator { + typedef bidirectional_iterator_tag iterator_category; + typedef T value_type; + typedef Distance difference_type; + typedef T* pointer; + typedef T& reference; +}; + +template <class T, class Distance> struct random_access_iterator { + typedef random_access_iterator_tag iterator_category; + typedef T value_type; + typedef Distance difference_type; + typedef T* pointer; + typedef T& reference; +}; + +#if 0 +template <class Category, class T, class Distance = ptrdiff_t, + class Pointer = T*, class Reference = T&> +struct iterator { + typedef Category iterator_category; + typedef T value_type; + typedef Distance difference_type; + typedef Pointer pointer; + typedef Reference reference; +}; +#endif + +#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION + +template <class Iterator> +struct iterator_traits { + typedef typename Iterator::iterator_category iterator_category; + typedef typename Iterator::value_type value_type; + typedef typename Iterator::difference_type difference_type; + typedef typename Iterator::pointer pointer; + typedef typename Iterator::reference reference; +}; + +template <class T> +struct iterator_traits<T*> { + typedef random_access_iterator_tag iterator_category; + typedef T value_type; + typedef ptrdiff_t difference_type; + typedef T* pointer; + typedef T& reference; +}; + +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +template <class T, class Distance> +inline input_iterator_tag +iterator_category(const input_iterator<T, Distance>&) { + return input_iterator_tag(); +} + +inline output_iterator_tag iterator_category(const output_iterator&) { + return output_iterator_tag(); +} + +template <class T, class Distance> +inline forward_iterator_tag +iterator_category(const forward_iterator<T, Distance>&) { + return forward_iterator_tag(); +} + +template <class T, class Distance> +inline bidirectional_iterator_tag +iterator_category(const bidirectional_iterator<T, Distance>&) { + return bidirectional_iterator_tag(); +} + +template <class T, class Distance> +inline random_access_iterator_tag +iterator_category(const random_access_iterator<T, Distance>&) { + return random_access_iterator_tag(); +} + +template <class T> +inline random_access_iterator_tag iterator_category(const T*) { + return random_access_iterator_tag(); +} + +template <class T, class Distance> +inline T* value_type(const input_iterator<T, Distance>&) { + return (T*)(0); +} + +template <class T, class Distance> +inline T* value_type(const forward_iterator<T, Distance>&) { + return (T*)(0); +} + +template <class T, class Distance> +inline T* value_type(const bidirectional_iterator<T, Distance>&) { + return (T*)(0); +} + +template <class T, class Distance> +inline T* value_type(const random_access_iterator<T, Distance>&) { + return (T*)(0); +} + +template <class T> +inline T* value_type(const T*) { return (T*)(0); } + +template <class T, class Distance> +inline Distance* distance_type(const input_iterator<T, Distance>&) { + return (Distance*)(0); +} + +template <class T, class Distance> +inline Distance* distance_type(const forward_iterator<T, Distance>&) { + return (Distance*)(0); +} + +template <class T, class Distance> +inline Distance* +distance_type(const bidirectional_iterator<T, Distance>&) { + return (Distance*)(0); +} + +template <class T, class Distance> +inline Distance* +distance_type(const random_access_iterator<T, Distance>&) { + return (Distance*)(0); +} + +template <class T> +inline ptrdiff_t* distance_type(const T*) { return (ptrdiff_t*)(0); } + +template <class Container> +class back_insert_iterator { +protected: + Container* container; +public: + typedef output_iterator_tag iterator_category; + + explicit back_insert_iterator(Container& x) : container(&x) {} + back_insert_iterator<Container>& + operator=(const typename Container::value_type& value) { + container->push_back(value); + return *this; + } + back_insert_iterator<Container>& operator*() { return *this; } + back_insert_iterator<Container>& operator++() { return *this; } + back_insert_iterator<Container>& operator++(int) { return *this; } +}; + +template <class Container> +inline output_iterator_tag +iterator_category(const back_insert_iterator<Container>&) +{ + return output_iterator_tag(); +} + +template <class Container> +inline back_insert_iterator<Container> back_inserter(Container& x) { + return back_insert_iterator<Container>(x); +} + +template <class Container> +class front_insert_iterator { +protected: + Container* container; +public: + typedef output_iterator_tag iterator_category; + + explicit front_insert_iterator(Container& x) : container(&x) {} + front_insert_iterator<Container>& + operator=(const typename Container::value_type& value) { + container->push_front(value); + return *this; + } + front_insert_iterator<Container>& operator*() { return *this; } + front_insert_iterator<Container>& operator++() { return *this; } + front_insert_iterator<Container>& operator++(int) { return *this; } +}; + +template <class Container> +inline output_iterator_tag +iterator_category(const front_insert_iterator<Container>&) +{ + return output_iterator_tag(); +} + +template <class Container> +inline front_insert_iterator<Container> front_inserter(Container& x) { + return front_insert_iterator<Container>(x); +} + +template <class Container> +class insert_iterator { +protected: + Container* container; + typename Container::iterator iter; +public: + typedef output_iterator_tag iterator_category; + + insert_iterator(Container& x, typename Container::iterator i) + : container(&x), iter(i) {} + insert_iterator<Container>& + operator=(const typename Container::value_type& value) { + iter = container->insert(iter, value); + ++iter; + return *this; + } + insert_iterator<Container>& operator*() { return *this; } + insert_iterator<Container>& operator++() { return *this; } + insert_iterator<Container>& operator++(int) { return *this; } +}; + +template <class Container> +inline output_iterator_tag +iterator_category(const insert_iterator<Container>&) +{ + return output_iterator_tag(); +} + +template <class Container, class Iterator> +inline insert_iterator<Container> inserter(Container& x, Iterator i) { + typedef typename Container::iterator iter; + return insert_iterator<Container>(x, iter(i)); +} + +#ifndef __STL_LIMITED_DEFAULT_TEMPLATES +template <class BidirectionalIterator, class T, class Reference = T&, + class Distance = ptrdiff_t> +#else +template <class BidirectionalIterator, class T, class Reference, + class Distance> +#endif +class reverse_bidirectional_iterator { + typedef reverse_bidirectional_iterator<BidirectionalIterator, T, Reference, + Distance> self; + friend bool operator==(const self& x, const self& y); +protected: + BidirectionalIterator current; +public: + typedef bidirectional_iterator_tag iterator_category; + typedef T value_type; + typedef Distance difference_type; + typedef T* pointer; + typedef Reference reference; + + reverse_bidirectional_iterator() {} + explicit reverse_bidirectional_iterator(BidirectionalIterator x) + : current(x) {} + BidirectionalIterator base() { return current; } + Reference operator*() const { + BidirectionalIterator tmp = current; + return *--tmp; + } + self& operator++() { + --current; + return *this; + } + self operator++(int) { + self tmp = *this; + --current; + return tmp; + } + self& operator--() { + ++current; + return *this; + } + self operator--(int) { + self tmp = *this; + ++current; + return tmp; + } +}; + + +template <class BidirectionalIterator, class T, class Reference, + class Distance> +inline bidirectional_iterator_tag +iterator_category(const reverse_bidirectional_iterator<BidirectionalIterator, + T, + Reference, Distance>&) { + return bidirectional_iterator_tag(); +} + +template <class BidirectionalIterator, class T, class Reference, + class Distance> +inline T* +value_type(const reverse_bidirectional_iterator<BidirectionalIterator, T, + Reference, Distance>&) { + return (T*) 0; +} + +template <class BidirectionalIterator, class T, class Reference, + class Distance> +inline Distance* +distance_type(const reverse_bidirectional_iterator<BidirectionalIterator, T, + Reference, Distance>&) { + return (Distance*) 0; +} + +template <class BidirectionalIterator, class T, class Reference, + class Distance> +inline bool operator==( + const reverse_bidirectional_iterator<BidirectionalIterator, T, Reference, + Distance>& x, + const reverse_bidirectional_iterator<BidirectionalIterator, T, Reference, + Distance>& y) { + return x.current == y.current; +} + +#ifndef __STL_LIMITED_DEFAULT_TEMPLATES +template <class RandomAccessIterator, class T, class Reference = T&, + class Distance = ptrdiff_t> +#else +template <class RandomAccessIterator, class T, class Reference, + class Distance> +#endif +class reverse_iterator { + typedef reverse_iterator<RandomAccessIterator, T, Reference, Distance> + self; + friend bool operator==(const self& x, const self& y); + friend bool operator<(const self& x, const self& y); + friend Distance operator-(const self& x, const self& y); + friend self operator+(Distance n, const self& x); +protected: + RandomAccessIterator current; +public: + typedef random_access_iterator_tag iterator_category; + typedef T value_type; + typedef Distance difference_type; + typedef T* pointer; + typedef Reference reference; + + reverse_iterator() {} + explicit reverse_iterator(RandomAccessIterator x) : current(x) {} + RandomAccessIterator base() { return current; } + Reference operator*() const { return *(current - 1); } + self& operator++() { + --current; + return *this; + } + self operator++(int) { + self tmp = *this; + --current; + return tmp; + } + self& operator--() { + ++current; + return *this; + } + self operator--(int) { + self tmp = *this; + ++current; + return tmp; + } + self operator+(Distance n) const { + return self(current - n); + } + self& operator+=(Distance n) { + current -= n; + return *this; + } + self operator-(Distance n) const { + return self(current + n); + } + self& operator-=(Distance n) { + current += n; + return *this; + } + Reference operator[](Distance n) { return *(*this + n); } +}; + +template <class RandomAccessIterator, class T, class Reference, class Distance> +inline random_access_iterator_tag +iterator_category(const reverse_iterator<RandomAccessIterator, T, + Reference, Distance>&) { + return random_access_iterator_tag(); +} + +template <class RandomAccessIterator, class T, class Reference, class Distance> +inline T* value_type(const reverse_iterator<RandomAccessIterator, T, + Reference, Distance>&) { + return (T*) 0; +} + +template <class RandomAccessIterator, class T, class Reference, class Distance> +inline Distance* distance_type(const reverse_iterator<RandomAccessIterator, T, + Reference, Distance>&) { + return (Distance*) 0; +} + + +template <class RandomAccessIterator, class T, class Reference, class Distance> +inline bool operator==(const reverse_iterator<RandomAccessIterator, T, + Reference, Distance>& x, + const reverse_iterator<RandomAccessIterator, T, + Reference, Distance>& y) { + return x.current == y.current; +} + +template <class RandomAccessIterator, class T, class Reference, class Distance> +inline bool operator<(const reverse_iterator<RandomAccessIterator, T, + Reference, Distance>& x, + const reverse_iterator<RandomAccessIterator, T, + Reference, Distance>& y) { + return y.current < x.current; +} + +template <class RandomAccessIterator, class T, class Reference, class Distance> +inline Distance operator-(const reverse_iterator<RandomAccessIterator, T, + Reference, Distance>& x, + const reverse_iterator<RandomAccessIterator, T, + Reference, Distance>& y) { + return y.current - x.current; +} + +template <class RandomAccessIterator, class T, class Reference, class Distance> +inline reverse_iterator<RandomAccessIterator, T, Reference, Distance> +operator+(Distance n, + const reverse_iterator<RandomAccessIterator, T, Reference, + Distance>& x) { + return reverse_iterator<RandomAccessIterator, T, Reference, Distance> + (x.current - n); +} + + +template <class ForwardIterator, class T> +class raw_storage_iterator { +protected: + ForwardIterator iter; +public: + typedef output_iterator_tag iterator_category; + + explicit raw_storage_iterator(ForwardIterator x) : iter(x) {} + raw_storage_iterator<ForwardIterator, T>& operator*() { return *this; } + raw_storage_iterator<ForwardIterator, T>& operator=(const T& element) { + construct(&*iter, element); + return *this; + } + raw_storage_iterator<ForwardIterator, T>& operator++() { + ++iter; + return *this; + } + raw_storage_iterator<ForwardIterator, T> operator++(int) { + raw_storage_iterator<ForwardIterator, T> tmp = *this; + ++iter; + return tmp; + } +}; + +template <class ForwardIterator, class T> +inline output_iterator_tag +iterator_category(const raw_storage_iterator<ForwardIterator, T>&) +{ + return output_iterator_tag(); +} + +template <class T, class Distance = ptrdiff_t> +class istream_iterator { +friend bool operator==(const istream_iterator<T, Distance>& x, + const istream_iterator<T, Distance>& y); +protected: + istream* stream; + T value; + bool end_marker; + void read() { + end_marker = (*stream) ? true : false; + if (end_marker) *stream >> value; + end_marker = (*stream) ? true : false; + } +public: + typedef input_iterator_tag iterator_category; + typedef T value_type; + typedef Distance difference_type; + typedef T* pointer; + typedef T& reference; + + istream_iterator() : stream(&cin), end_marker(false) {} + istream_iterator(istream& s) : stream(&s) { read(); } + const T& operator*() const { return value; } + istream_iterator<T, Distance>& operator++() { + read(); + return *this; + } + istream_iterator<T, Distance> operator++(int) { + istream_iterator<T, Distance> tmp = *this; + read(); + return tmp; + } +}; + +template <class T, class Distance> +inline input_iterator_tag +iterator_category(const istream_iterator<T, Distance>&) { + return input_iterator_tag(); +} + +template <class T, class Distance> +inline T* value_type(const istream_iterator<T, Distance>&) { return (T*) 0; } + +template <class T, class Distance> +inline Distance* distance_type(const istream_iterator<T, Distance>&) { + return (Distance*) 0; +} + +template <class T, class Distance> +bool operator==(const istream_iterator<T, Distance>& x, + const istream_iterator<T, Distance>& y) { + return x.stream == y.stream && x.end_marker == y.end_marker || + x.end_marker == false && y.end_marker == false; +} + +template <class T> +class ostream_iterator { +protected: + ostream* stream; + const char* string; +public: + typedef output_iterator_tag iterator_category; + + ostream_iterator(ostream& s) : stream(&s), string(0) {} + ostream_iterator(ostream& s, const char* c) : stream(&s), string(c) {} + ostream_iterator<T>& operator=(const T& value) { + *stream << value; + if (string) *stream << string; + return *this; + } + ostream_iterator<T>& operator*() { return *this; } + ostream_iterator<T>& operator++() { return *this; } + ostream_iterator<T>& operator++(int) { return *this; } +}; + +template <class T> +inline output_iterator_tag +iterator_category(const ostream_iterator<T>&) { + return output_iterator_tag(); +} + +#endif /* __SGI_STL_ITERATOR_H */ diff --git a/libstdc++/stl/list.h b/libstdc++/stl/list.h new file mode 100644 index 0000000..b26692b --- /dev/null +++ b/libstdc++/stl/list.h @@ -0,0 +1,624 @@ +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#ifndef __SGI_STL_LIST_H +#define __SGI_STL_LIST_H + +#include <stddef.h> +#include <algobase.h> +#include <iterator.h> +#include <alloc.h> + +template <class T> +struct __list_node { + typedef void* void_pointer; + void_pointer next; + void_pointer prev; + T data; +}; + +template<class T, class Ref> +struct __list_iterator { + typedef __list_iterator<T, T&> iterator; + typedef __list_iterator<T, const T&> const_iterator; + typedef __list_iterator<T, Ref> self; + + typedef bidirectional_iterator_tag iterator_category; + typedef T value_type; + typedef value_type* pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef __list_node<T>* link_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + link_type node; + + __list_iterator(link_type x) : node(x) {} + __list_iterator() {} + __list_iterator(const iterator& x) : node(x.node) {} + + bool operator==(const self& x) const { return node == x.node; } + bool operator!=(const self& x) const { return node != x.node; } + Ref operator*() const { return (*node).data; } + + self& operator++() { + node = (link_type)((*node).next); + return *this; + } + self operator++(int) { + self tmp = *this; + ++*this; + return tmp; + } + self& operator--() { + node = (link_type)((*node).prev); + return *this; + } + self operator--(int) { + self tmp = *this; + --*this; + return tmp; + } +}; + + +template <class T, class Ref> +inline bidirectional_iterator_tag +iterator_category(const __list_iterator<T, Ref>&) { + return bidirectional_iterator_tag(); +} + +template <class T, class Ref> +inline T* +value_type(const __list_iterator<T, Ref>&) { + return 0; +} + +template <class T, class Ref> +inline ptrdiff_t* +distance_type(const __list_iterator<T, Ref>&) { + return 0; +} + + +template <class T, class Alloc = alloc> +class list { +protected: + typedef void* void_pointer; + typedef __list_node<T> list_node; + typedef simple_alloc<list_node, Alloc> list_node_allocator; +public: + typedef T value_type; + typedef value_type* pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef list_node* link_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + +public: + typedef __list_iterator<T, T&> iterator; + typedef __list_iterator<T, const T&> const_iterator; + + typedef reverse_bidirectional_iterator<const_iterator, value_type, + const_reference, difference_type> + const_reverse_iterator; + typedef reverse_bidirectional_iterator<iterator, value_type, reference, + difference_type> + reverse_iterator; + +protected: + link_type get_node() { return list_node_allocator::allocate(); } + void put_node(link_type p) { list_node_allocator::deallocate(p); } + + link_type create_node(const T& x) { + link_type p = get_node(); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + construct(&p->data, x); + return p; +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + put_node(p); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } + void destroy_node(link_type p) { + destroy(&p->data); + put_node(p); + } + +protected: + void empty_initialize() { + node = get_node(); + node->next = node; + node->prev = node; + } + + void fill_initialize(size_type n, const T& value) { + empty_initialize(); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + insert(begin(), n, value); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + clear(); + put_node(node); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } + +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + void range_initialize(InputIterator first, InputIterator last) { + empty_initialize(); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + insert(begin(), first, last); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + clear(); + put_node(node); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } +#else /* __STL_MEMBER_TEMPLATES */ + void range_initialize(const T* first, const T* last) { + empty_initialize(); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + insert(begin(), first, last); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + clear(); + put_node(node); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } + void range_initialize(const_iterator first, const_iterator last) { + empty_initialize(); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + insert(begin(), first, last); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + clear(); + put_node(node); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } +#endif /* __STL_MEMBER_TEMPLATES */ + +protected: + link_type node; + +public: + list() { empty_initialize(); } + + iterator begin() { return (link_type)((*node).next); } + const_iterator begin() const { return (link_type)((*node).next); } + iterator end() { return node; } + const_iterator end() const { return node; } + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + bool empty() const { return node->next == node; } + size_type size() const { + size_type result = 0; + distance(begin(), end(), result); + return result; + } + size_type max_size() const { return size_type(-1); } + reference front() { return *begin(); } + const_reference front() const { return *begin(); } + reference back() { return *(--end()); } + const_reference back() const { return *(--end()); } + void swap(list<T, Alloc>& x) { ::swap(node, x.node); } + iterator insert(iterator position, const T& x) { + link_type tmp = create_node(x); + tmp->next = position.node; + tmp->prev = position.node->prev; + (link_type(position.node->prev))->next = tmp; + position.node->prev = tmp; + return tmp; + } + iterator insert(iterator position) { return insert(position, T()); } +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + void insert(iterator position, InputIterator first, InputIterator last); +#else /* __STL_MEMBER_TEMPLATES */ + void insert(iterator position, const T* first, const T* last); + void insert(iterator position, + const_iterator first, const_iterator last); +#endif /* __STL_MEMBER_TEMPLATES */ + void insert(iterator pos, size_type n, const T& x); + void insert(iterator pos, int n, const T& x) { + insert(pos, (size_type)n, x); + } + void insert(iterator pos, long n, const T& x) { + insert(pos, (size_type)n, x); + } + + void push_front(const T& x) { insert(begin(), x); } + void push_back(const T& x) { insert(end(), x); } + void erase(iterator position) { + (link_type(position.node->prev))->next = position.node->next; + (link_type(position.node->next))->prev = position.node->prev; + destroy_node(position.node); + } + void erase(iterator first, iterator last); + void resize(size_type new_size, const T& x); + void resize(size_type new_size) { resize(new_size, T()); } + void clear(); + + void pop_front() { erase(begin()); } + void pop_back() { + iterator tmp = end(); + erase(--tmp); + } + list(size_type n, const T& value) { fill_initialize(n, value); } + list(int n, const T& value) { fill_initialize(n, value); } + list(long n, const T& value) { fill_initialize(n, value); } + explicit list(size_type n) { fill_initialize(n, T()); } + +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + list(InputIterator first, InputIterator last) { + range_initialize(first, last); + } + +#else /* __STL_MEMBER_TEMPLATES */ + list(const T* first, const T* last) { range_initialize(first, last); } + list(const_iterator first, const_iterator last) { + range_initialize(first, last); + } +#endif /* __STL_MEMBER_TEMPLATES */ + list(const list<T, Alloc>& x) { + range_initialize(x.begin(), x.end()); + } + ~list() { + clear(); + put_node(node); + } + list<T, Alloc>& operator=(const list<T, Alloc>& x); + +protected: + void transfer(iterator position, iterator first, iterator last) { + if (position != last) { + (*(link_type((*last.node).prev))).next = position.node; + (*(link_type((*first.node).prev))).next = last.node; + (*(link_type((*position.node).prev))).next = first.node; + link_type tmp = link_type((*position.node).prev); + (*position.node).prev = (*last.node).prev; + (*last.node).prev = (*first.node).prev; + (*first.node).prev = tmp; + } + } + +public: + void splice(iterator position, list& x) { + if (!x.empty()) + transfer(position, x.begin(), x.end()); + } + void splice(iterator position, list&, iterator i) { + iterator j = i; + ++j; + if (position == i || position == j) return; + transfer(position, i, j); + } + void splice(iterator position, list&, iterator first, iterator last) { + if (first != last) + transfer(position, first, last); + } + void remove(const T& value); + void unique(); + void merge(list& x); + void reverse(); + void sort(); + +#ifdef __STL_MEMBER_TEMPLATES + template <class Predicate> void remove_if(Predicate); + template <class BinaryPredicate> void unique(BinaryPredicate); + template <class StrictWeakOrdering> void merge(list&, StrictWeakOrdering); + template <class StrictWeakOrdering> void sort(StrictWeakOrdering); +#endif /* __STL_MEMBER_TEMPLATES */ + + friend bool operator== (const list& x, const list& y); +}; + +template <class T, class Alloc> +inline bool operator==(const list<T,Alloc>& x, const list<T,Alloc>& y) { + typedef list<T,Alloc>::link_type link_type; + link_type e1 = x.node; + link_type e2 = y.node; + link_type n1 = (link_type) e1->next; + link_type n2 = (link_type) e2->next; + for ( ; n1 != e1 && n2 != e2 ; + n1 = (link_type) n1->next, n2 = (link_type) n2->next) + if (n1->data != n2->data) + return false; + return n1 == e1 && n2 == e2; +} + +template <class T, class Alloc> +inline bool operator<(const list<T, Alloc>& x, const list<T, Alloc>& y) { + return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); +} + +#ifdef __STL_MEMBER_TEMPLATES + +template <class T, class Alloc> template <class InputIterator> +void list<T, Alloc>::insert(iterator position, + InputIterator first, InputIterator last) { + for ( ; first != last; ++first) + insert(position, *first); +} + +#else /* __STL_MEMBER_TEMPLATES */ + +template <class T, class Alloc> +void list<T, Alloc>::insert(iterator position, const T* first, const T* last) { + for ( ; first != last; ++first) + insert(position, *first); +} + +template <class T, class Alloc> +void list<T, Alloc>::insert(iterator position, + const_iterator first, const_iterator last) { + for ( ; first != last; ++first) + insert(position, *first); +} + +#endif /* __STL_MEMBER_TEMPLATES */ + +template <class T, class Alloc> +void list<T, Alloc>::insert(iterator position, size_type n, const T& x) { + for ( ; n > 0; --n) + insert(position, x); +} + +template <class T, class Alloc> +void list<T, Alloc>::erase(iterator first, iterator last) { + while (first != last) erase(first++); +} + +template <class T, class Alloc> +void list<T, Alloc>::resize(size_type new_size, const T& x) +{ + size_type len = size(); + if (new_size < len) { + iterator f; + if (new_size < len / 2) { + f = begin(); + advance(f, new_size); + } + else { + f = end(); + advance(f, difference_type(len) - difference_type(new_size)); + } + erase(f, end()); + } + else + insert(end(), new_size - len, x); +} + +template <class T, class Alloc> +void list<T, Alloc>::clear() +{ + link_type cur = (link_type) node->next; + while (cur != node) { + link_type tmp = cur; + cur = (link_type) cur->next; + destroy_node(tmp); + } + node->next = node; + node->prev = node; +} + +template <class T, class Alloc> +list<T, Alloc>& list<T, Alloc>::operator=(const list<T, Alloc>& x) { + if (this != &x) { + iterator first1 = begin(); + iterator last1 = end(); + const_iterator first2 = x.begin(); + const_iterator last2 = x.end(); + while (first1 != last1 && first2 != last2) *first1++ = *first2++; + if (first2 == last2) + erase(first1, last1); + else + insert(last1, first2, last2); + } + return *this; +} + +template <class T, class Alloc> +void list<T, Alloc>::remove(const T& value) { + iterator first = begin(); + iterator last = end(); + while (first != last) { + iterator next = first; + ++next; + if (*first == value) erase(first); + first = next; + } +} + +template <class T, class Alloc> +void list<T, Alloc>::unique() { + iterator first = begin(); + iterator last = end(); + if (first == last) return; + iterator next = first; + while (++next != last) { + if (*first == *next) + erase(next); + else + first = next; + next = first; + } +} + +template <class T, class Alloc> +void list<T, Alloc>::merge(list<T, Alloc>& x) { + iterator first1 = begin(); + iterator last1 = end(); + iterator first2 = x.begin(); + iterator last2 = x.end(); + while (first1 != last1 && first2 != last2) + if (*first2 < *first1) { + iterator next = first2; + transfer(first1, first2, ++next); + first2 = next; + } + else + ++first1; + if (first2 != last2) transfer(last1, first2, last2); +} + +template <class T, class Alloc> +void list<T, Alloc>::reverse() { + if (node->next == node || link_type(node->next)->next == node) return; + iterator first = begin(); + ++first; + while (first != end()) { + iterator old = first; + ++first; + transfer(begin(), old, first); + } +} + +template <class T, class Alloc> +void list<T, Alloc>::sort() { + if (node->next == node || link_type(node->next)->next == node) return; + list<T, Alloc> carry; + list<T, Alloc> counter[64]; + int fill = 0; + while (!empty()) { + carry.splice(carry.begin(), *this, begin()); + int i = 0; + while(i < fill && !counter[i].empty()) { + counter[i].merge(carry); + carry.swap(counter[i++]); + } + carry.swap(counter[i]); + if (i == fill) ++fill; + } + + for (int i = 1; i < fill; ++i) counter[i].merge(counter[i-1]); + swap(counter[fill-1]); +} + +#ifdef __STL_MEMBER_TEMPLATES + +template <class T, class Alloc> template <class Predicate> +void list<T, Alloc>::remove_if(Predicate pred) { + iterator first = begin(); + iterator last = end(); + while (first != last) { + iterator next = first; + ++next; + if (pred(*first)) erase(first); + first = next; + } +} + +template <class T, class Alloc> template <class BinaryPredicate> +void list<T, Alloc>::unique(BinaryPredicate binary_pred) { + iterator first = begin(); + iterator last = end(); + if (first == last) return; + iterator next = first; + while (++next != last) { + if (binary_pred(*first, *next)) + erase(next); + else + first = next; + next = first; + } +} + +template <class T, class Alloc> template <class StrictWeakOrdering> +void list<T, Alloc>::merge(list<T, Alloc>& x, StrictWeakOrdering comp) { + iterator first1 = begin(); + iterator last1 = end(); + iterator first2 = x.begin(); + iterator last2 = x.end(); + while (first1 != last1 && first2 != last2) + if (comp(*first2, *first1)) { + iterator next = first2; + transfer(first1, first2, ++next); + first2 = next; + } + else + ++first1; + if (first2 != last2) transfer(last1, first2, last2); +} + +template <class T, class Alloc> template <class StrictWeakOrdering> +void list<T, Alloc>::sort(StrictWeakOrdering comp) { + if (node->next == node || link_type(node->next)->next == node) return; + list<T, Alloc> carry; + list<T, Alloc> counter[64]; + int fill = 0; + while (!empty()) { + carry.splice(carry.begin(), *this, begin()); + int i = 0; + while(i < fill && !counter[i].empty()) { + counter[i].merge(carry, comp); + carry.swap(counter[i++]); + } + carry.swap(counter[i]); + if (i == fill) ++fill; + } + + for (int i = 1; i < fill; ++i) counter[i].merge(counter[i-1], comp); + swap(counter[fill-1]); +} + +#endif /* __STL_MEMBER_TEMPLATES */ + +#endif /* __SGI_STL_LIST_H */ diff --git a/libstdc++/stl/map.h b/libstdc++/stl/map.h new file mode 100644 index 0000000..5c9d6b1 --- /dev/null +++ b/libstdc++/stl/map.h @@ -0,0 +1,188 @@ +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#ifndef __SGI_STL_MAP_H +#define __SGI_STL_MAP_H + +#include <tree.h> + +#ifndef __STL_LIMITED_DEFAULT_TEMPLATES +template <class Key, class T, class Compare = less<Key>, class Alloc = alloc> +#else +template <class Key, class T, class Compare, class Alloc = alloc> +#endif +class map { +public: + +// typedefs: + + typedef Key key_type; + typedef T data_type; + typedef pair<const Key, T> value_type; + typedef Compare key_compare; + + class value_compare + : public binary_function<value_type, value_type, bool> { + friend class map<Key, T, Compare, Alloc>; + protected : + Compare comp; + value_compare(Compare c) : comp(c) {} + public: + bool operator()(const value_type& x, const value_type& y) const { + return comp(x.first, y.first); + } + }; + +private: + typedef rb_tree<key_type, value_type, + select1st<value_type>, key_compare, Alloc> rep_type; + rep_type t; // red-black tree representing map +public: + typedef rep_type::pointer pointer; + typedef rep_type::reference reference; + typedef rep_type::const_reference const_reference; + typedef rep_type::iterator iterator; + typedef rep_type::const_iterator const_iterator; + typedef rep_type::reverse_iterator reverse_iterator; + typedef rep_type::const_reverse_iterator const_reverse_iterator; + typedef rep_type::size_type size_type; + typedef rep_type::difference_type difference_type; + + // allocation/deallocation + + map() : t(Compare()) {} + explicit map(const Compare& comp) : t(comp) {} + +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + map(InputIterator first, InputIterator last) + : t(Compare()) { t.insert_unique(first, last); } + + template <class InputIterator> + map(InputIterator first, InputIterator last, const Compare& comp) + : t(comp) { t.insert_unique(first, last); } +#else + map(const value_type* first, const value_type* last) + : t(Compare()) { t.insert_unique(first, last); } + map(const value_type* first, const value_type* last, const Compare& comp) + : t(comp) { t.insert_unique(first, last); } + + map(const_iterator first, const_iterator last) + : t(Compare()) { t.insert_unique(first, last); } + map(const_iterator first, const_iterator last, const Compare& comp) + : t(comp) { t.insert_unique(first, last); } +#endif /* __STL_MEMBER_TEMPLATES */ + + map(const map<Key, T, Compare, Alloc>& x) : t(x.t) {} + map<Key, T, Compare, Alloc>& operator=(const map<Key, T, Compare, Alloc>& x) + { + t = x.t; + return *this; + } + + // accessors: + + key_compare key_comp() const { return t.key_comp(); } + value_compare value_comp() const { return value_compare(t.key_comp()); } + iterator begin() { return t.begin(); } + const_iterator begin() const { return t.begin(); } + iterator end() { return t.end(); } + const_iterator end() const { return t.end(); } + reverse_iterator rbegin() { return t.rbegin(); } + const_reverse_iterator rbegin() const { return t.rbegin(); } + reverse_iterator rend() { return t.rend(); } + const_reverse_iterator rend() const { return t.rend(); } + bool empty() const { return t.empty(); } + size_type size() const { return t.size(); } + size_type max_size() const { return t.max_size(); } + T& operator[](const key_type& k) { + return (*((insert(value_type(k, T()))).first)).second; + } + void swap(map<Key, T, Compare, Alloc>& x) { t.swap(x.t); } + + // insert/erase + + pair<iterator,bool> insert(const value_type& x) { return t.insert_unique(x); } + iterator insert(iterator position, const value_type& x) { + return t.insert_unique(position, x); + } +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + void insert(InputIterator first, InputIterator last) { + t.insert_unique(first, last); + } +#else + void insert(const value_type* first, const value_type* last) { + t.insert_unique(first, last); + } + void insert(const_iterator first, const_iterator last) { + t.insert_unique(first, last); + } +#endif /* __STL_MEMBER_TEMPLATES */ + + void erase(iterator position) { t.erase(position); } + size_type erase(const key_type& x) { return t.erase(x); } + void erase(iterator first, iterator last) { t.erase(first, last); } + void clear() { t.clear(); } + + // map operations: + + iterator find(const key_type& x) { return t.find(x); } + const_iterator find(const key_type& x) const { return t.find(x); } + size_type count(const key_type& x) const { return t.count(x); } + iterator lower_bound(const key_type& x) {return t.lower_bound(x); } + const_iterator lower_bound(const key_type& x) const { + return t.lower_bound(x); + } + iterator upper_bound(const key_type& x) {return t.upper_bound(x); } + const_iterator upper_bound(const key_type& x) const { + return t.upper_bound(x); + } + + pair<iterator,iterator> equal_range(const key_type& x) { + return t.equal_range(x); + } + pair<const_iterator,const_iterator> equal_range(const key_type& x) const { + return t.equal_range(x); + } + friend bool operator==(const map&, const map&); + friend bool operator<(const map&, const map&); +}; + +template <class Key, class T, class Compare, class Alloc> +inline bool operator==(const map<Key, T, Compare, Alloc>& x, + const map<Key, T, Compare, Alloc>& y) { + return x.t == y.t; +} + +template <class Key, class T, class Compare, class Alloc> +inline bool operator<(const map<Key, T, Compare, Alloc>& x, + const map<Key, T, Compare, Alloc>& y) { + return x.t < y.t; +} + +#endif /* __SGI_STL_MAP_H */ + diff --git a/libstdc++/stl/multimap.h b/libstdc++/stl/multimap.h new file mode 100644 index 0000000..f15880a --- /dev/null +++ b/libstdc++/stl/multimap.h @@ -0,0 +1,182 @@ +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#ifndef __SGI_STL_MULTIMAP_H +#define __SGI_STL_MULTIMAP_H + +#include <tree.h> + +#ifndef __STL_LIMITED_DEFAULT_TEMPLATES +template <class Key, class T, class Compare = less<Key>, class Alloc = alloc> +#else +template <class Key, class T, class Compare, class Alloc = alloc> +#endif +class multimap { +public: + +// typedefs: + + typedef Key key_type; + typedef T data_type; + typedef pair<const Key, T> value_type; + typedef Compare key_compare; + + class value_compare : public binary_function<value_type, value_type, bool> { + friend class multimap<Key, T, Compare, Alloc>; + protected: + Compare comp; + value_compare(Compare c) : comp(c) {} + public: + bool operator()(const value_type& x, const value_type& y) const { + return comp(x.first, y.first); + } + }; + +private: + typedef rb_tree<key_type, value_type, + select1st<value_type>, key_compare, Alloc> rep_type; + rep_type t; // red-black tree representing multimap +public: + typedef rep_type::pointer pointer; + typedef rep_type::reference reference; + typedef rep_type::const_reference const_reference; + typedef rep_type::iterator iterator; + typedef rep_type::const_iterator const_iterator; + typedef rep_type::reverse_iterator reverse_iterator; + typedef rep_type::const_reverse_iterator const_reverse_iterator; + typedef rep_type::size_type size_type; + typedef rep_type::difference_type difference_type; + +// allocation/deallocation + + multimap() : t(Compare()) { } + explicit multimap(const Compare& comp) : t(comp) { } + +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + multimap(InputIterator first, InputIterator last) + : t(Compare()) { t.insert_equal(first, last); } + + template <class InputIterator> + multimap(InputIterator first, InputIterator last, const Compare& comp) + : t(comp) { t.insert_equal(first, last); } +#else + multimap(const value_type* first, const value_type* last) + : t(Compare()) { t.insert_equal(first, last); } + multimap(const value_type* first, const value_type* last, + const Compare& comp) + : t(comp) { t.insert_equal(first, last); } + + multimap(const_iterator first, const_iterator last) + : t(Compare()) { t.insert_equal(first, last); } + multimap(const_iterator first, const_iterator last, const Compare& comp) + : t(comp) { t.insert_equal(first, last); } +#endif /* __STL_MEMBER_TEMPLATES */ + + multimap(const multimap<Key, T, Compare, Alloc>& x) : t(x.t) { } + multimap<Key, T, Compare, Alloc>& + operator=(const multimap<Key, T, Compare, Alloc>& x) { + t = x.t; + return *this; + } + + // accessors: + + key_compare key_comp() const { return t.key_comp(); } + value_compare value_comp() const { return value_compare(t.key_comp()); } + iterator begin() { return t.begin(); } + const_iterator begin() const { return t.begin(); } + iterator end() { return t.end(); } + const_iterator end() const { return t.end(); } + reverse_iterator rbegin() { return t.rbegin(); } + const_reverse_iterator rbegin() const { return t.rbegin(); } + reverse_iterator rend() { return t.rend(); } + const_reverse_iterator rend() const { return t.rend(); } + bool empty() const { return t.empty(); } + size_type size() const { return t.size(); } + size_type max_size() const { return t.max_size(); } + void swap(multimap<Key, T, Compare, Alloc>& x) { t.swap(x.t); } + + // insert/erase + + iterator insert(const value_type& x) { return t.insert_equal(x); } + iterator insert(iterator position, const value_type& x) { + return t.insert_equal(position, x); + } +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + void insert(InputIterator first, InputIterator last) { + t.insert_equal(first, last); + } +#else + void insert(const value_type* first, const value_type* last) { + t.insert_equal(first, last); + } + void insert(const_iterator first, const_iterator last) { + t.insert_equal(first, last); + } +#endif /* __STL_MEMBER_TEMPLATES */ + void erase(iterator position) { t.erase(position); } + size_type erase(const key_type& x) { return t.erase(x); } + void erase(iterator first, iterator last) { t.erase(first, last); } + void clear() { t.clear(); } + + // multimap operations: + + iterator find(const key_type& x) { return t.find(x); } + const_iterator find(const key_type& x) const { return t.find(x); } + size_type count(const key_type& x) const { return t.count(x); } + iterator lower_bound(const key_type& x) {return t.lower_bound(x); } + const_iterator lower_bound(const key_type& x) const { + return t.lower_bound(x); + } + iterator upper_bound(const key_type& x) {return t.upper_bound(x); } + const_iterator upper_bound(const key_type& x) const { + return t.upper_bound(x); + } + pair<iterator,iterator> equal_range(const key_type& x) { + return t.equal_range(x); + } + pair<const_iterator,const_iterator> equal_range(const key_type& x) const { + return t.equal_range(x); + } + friend bool operator==(const multimap&, const multimap&); + friend bool operator<(const multimap&, const multimap&); +}; + +template <class Key, class T, class Compare, class Alloc> +inline bool operator==(const multimap<Key, T, Compare, Alloc>& x, + const multimap<Key, T, Compare, Alloc>& y) { + return x.t == y.t; +} + +template <class Key, class T, class Compare, class Alloc> +inline bool operator<(const multimap<Key, T, Compare, Alloc>& x, + const multimap<Key, T, Compare, Alloc>& y) { + return x.t < y.t; +} + +#endif /* __SGI_STL_MULTIMAP_H */ diff --git a/libstdc++/stl/multiset.h b/libstdc++/stl/multiset.h new file mode 100644 index 0000000..3df4557 --- /dev/null +++ b/libstdc++/stl/multiset.h @@ -0,0 +1,167 @@ +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#ifndef __SGI_STL_MULTISET_H +#define __SGI_STL_MULTISET_H + +#include <tree.h> + +#ifndef __STL_LIMITED_DEFAULT_TEMPLATES +template <class Key, class Compare = less<Key>, class Alloc = alloc> +#else +template <class Key, class Compare, class Alloc = alloc> +#endif +class multiset { +public: + // typedefs: + + typedef Key key_type; + typedef Key value_type; + typedef Compare key_compare; + typedef Compare value_compare; +private: + typedef rb_tree<key_type, value_type, + identity<value_type>, key_compare, Alloc> rep_type; + rep_type t; // red-black tree representing multiset +public: + typedef rep_type::const_pointer pointer; + typedef rep_type::const_reference reference; + typedef rep_type::const_reference const_reference; + typedef rep_type::const_iterator iterator; + typedef rep_type::const_iterator const_iterator; + typedef rep_type::const_reverse_iterator reverse_iterator; + typedef rep_type::const_reverse_iterator const_reverse_iterator; + typedef rep_type::size_type size_type; + typedef rep_type::difference_type difference_type; + + // allocation/deallocation + + multiset() : t(Compare()) {} + explicit multiset(const Compare& comp) : t(comp) {} + +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + multiset(InputIterator first, InputIterator last) + : t(Compare()) { t.insert_equal(first, last); } + template <class InputIterator> + multiset(InputIterator first, InputIterator last, const Compare& comp) + : t(comp) { t.insert_equal(first, last); } +#else + multiset(const value_type* first, const value_type* last) + : t(Compare()) { t.insert_equal(first, last); } + multiset(const value_type* first, const value_type* last, + const Compare& comp) + : t(comp) { t.insert_equal(first, last); } + + multiset(const_iterator first, const_iterator last) + : t(Compare()) { t.insert_equal(first, last); } + multiset(const_iterator first, const_iterator last, const Compare& comp) + : t(comp) { t.insert_equal(first, last); } +#endif /* __STL_MEMBER_TEMPLATES */ + + multiset(const multiset<Key, Compare, Alloc>& x) : t(x.t) {} + multiset<Key, Compare, Alloc>& + operator=(const multiset<Key, Compare, Alloc>& x) { + t = x.t; + return *this; + } + + // accessors: + + key_compare key_comp() const { return t.key_comp(); } + value_compare value_comp() const { return t.key_comp(); } + iterator begin() const { return t.begin(); } + iterator end() const { return t.end(); } + reverse_iterator rbegin() const { return t.rbegin(); } + reverse_iterator rend() const { return t.rend(); } + bool empty() const { return t.empty(); } + size_type size() const { return t.size(); } + size_type max_size() const { return t.max_size(); } + void swap(multiset<Key, Compare, Alloc>& x) { t.swap(x.t); } + + // insert/erase + iterator insert(const value_type& x) { + return t.insert_equal(x); + } + iterator insert(iterator position, const value_type& x) { + return t.insert_equal((rep_type::iterator&)position, x); + } + +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + void insert(InputIterator first, InputIterator last) { + t.insert_equal(first, last); + } +#else + void insert(const value_type* first, const value_type* last) { + t.insert_equal(first, last); + } + void insert(const_iterator first, const_iterator last) { + t.insert_equal(first, last); + } +#endif /* __STL_MEMBER_TEMPLATES */ + void erase(iterator position) { + t.erase((rep_type::iterator&)position); + } + size_type erase(const key_type& x) { + return t.erase(x); + } + void erase(iterator first, iterator last) { + t.erase((rep_type::iterator&)first, + (rep_type::iterator&)last); + } + void clear() { t.clear(); } + + // multiset operations: + + iterator find(const key_type& x) const { return t.find(x); } + size_type count(const key_type& x) const { return t.count(x); } + iterator lower_bound(const key_type& x) const { + return t.lower_bound(x); + } + iterator upper_bound(const key_type& x) const { + return t.upper_bound(x); + } + pair<iterator,iterator> equal_range(const key_type& x) const { + return t.equal_range(x); + } + friend bool operator==(const multiset&, const multiset&); + friend bool operator<(const multiset&, const multiset&); +}; + +template <class Key, class Compare, class Alloc> +inline bool operator==(const multiset<Key, Compare, Alloc>& x, + const multiset<Key, Compare, Alloc>& y) { + return x.t == y.t; +} + +template <class Key, class Compare, class Alloc> +inline bool operator<(const multiset<Key, Compare, Alloc>& x, + const multiset<Key, Compare, Alloc>& y) { + return x.t < y.t; +} + +#endif /* __SGI_STL_MULTISET_H */ diff --git a/libstdc++/stl/pair.h b/libstdc++/stl/pair.h new file mode 100644 index 0000000..ca20d8b --- /dev/null +++ b/libstdc++/stl/pair.h @@ -0,0 +1,63 @@ +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#ifndef PAIR_H +#define PAIR_H + +#include <stl_config.h> + +template <class T1, class T2> +struct pair { + typedef T1 first_type; + typedef T2 second_type; + + T1 first; + T2 second; + pair() : first(T1()), second(T2()) {} + pair(const T1& a, const T2& b) : first(a), second(b) {} + +#ifdef __STL_MEMBER_TEMPLATES + template <class U1, class U2> + pair(const pair<U1, U2>& p) : first(p.first), second(p.second) {} +#endif +}; + +template <class T1, class T2> +inline bool operator==(const pair<T1, T2>& x, const pair<T1, T2>& y) { + return x.first == y.first && x.second == y.second; +} + +template <class T1, class T2> +inline bool operator<(const pair<T1, T2>& x, const pair<T1, T2>& y) { + return x.first < y.first || (!(y.first < x.first) && x.second < y.second); +} + +template <class T1, class T2> +inline pair<T1, T2> make_pair(const T1& x, const T2& y) { + return pair<T1, T2>(x, y); +} + +#endif diff --git a/libstdc++/stl/pthread_alloc.h b/libstdc++/stl/pthread_alloc.h new file mode 100644 index 0000000..a2aeaa1 --- /dev/null +++ b/libstdc++/stl/pthread_alloc.h @@ -0,0 +1,344 @@ +/* + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#ifndef __PTHREAD_ALLOC_H +#define __PTHREAD_ALLOC_H + +// Pthread-specific node allocator. +// This is similar to the default allocator, except that free-list +// information is kept separately for each thread, avoiding locking. +// This should be reasonably fast even in the presence of threads. +// The down side is that storage may not be well-utilized. +// It is not an error to allocate memory in thread A and deallocate +// it n thread B. But this effectively transfers ownership of the memory, +// so that it can only be reallocated by thread B. Thus this can effectively +// result in a storage leak if it's done on a regular basis. +// It can also result in frequent sharing of +// cache lines among processors, with potentially serious performance +// consequences. + + +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <pthread.h> +#include <alloc.h> +#ifndef __RESTRICT +# define __RESTRICT +#endif + +// Note that this class has nonstatic members. We instantiate it once +// per thread. +template <bool dummy> +class __pthread_alloc_template { + +private: + enum {ALIGN = 8}; + enum {MAX_BYTES = 128}; // power of 2 + enum {NFREELISTS = MAX_BYTES/ALIGN}; + + union obj { + union obj * free_list_link; + char client_data[ALIGN]; /* The client sees this. */ + }; + + // Per instance state + obj* volatile free_list[NFREELISTS]; + __pthread_alloc_template<dummy>* next; // Free list link + + static size_t ROUND_UP(size_t bytes) { + return (((bytes) + ALIGN-1) & ~(ALIGN - 1)); + } + static size_t FREELIST_INDEX(size_t bytes) { + return (((bytes) + ALIGN-1)/ALIGN - 1); + } + + // Returns an object of size n, and optionally adds to size n free list. + void *refill(size_t n); + // Allocates a chunk for nobjs of size size. nobjs may be reduced + // if it is inconvenient to allocate the requested number. + static char *chunk_alloc(size_t size, int &nobjs); + + // Chunk allocation state. And other shared state. + // Protected by chunk_allocator_lock. + static pthread_mutex_t chunk_allocator_lock; + static char *start_free; + static char *end_free; + static size_t heap_size; + static __pthread_alloc_template<dummy>* free_allocators; + static pthread_key_t key; + static bool key_initialized; + // Pthread key under which allocator is stored. + // Allocator instances that are currently unclaimed by any thread. + static void destructor(void *instance); + // Function to be called on thread exit to reclaim allocator + // instance. + static __pthread_alloc_template<dummy> *new_allocator(); + // Return a recycled or new allocator instance. + static __pthread_alloc_template<dummy> *get_allocator_instance(); + // ensure that the current thread has an associated + // allocator instance. + class lock { + public: + lock () { pthread_mutex_lock(&chunk_allocator_lock); } + ~lock () { pthread_mutex_unlock(&chunk_allocator_lock); } + }; + friend class lock; + + +public: + + __pthread_alloc_template() : next(0) + { + memset((void *)free_list, 0, NFREELISTS * sizeof(obj *)); + } + + /* n must be > 0 */ + static void * allocate(size_t n) + { + obj * volatile * my_free_list; + obj * __RESTRICT result; + __pthread_alloc_template<dummy>* a; + + if (n > MAX_BYTES) { + return(malloc(n)); + } + if (!key_initialized || + !(a = (__pthread_alloc_template<dummy>*) + pthread_getspecific(key))) { + a = get_allocator_instance(); + } + my_free_list = a -> free_list + FREELIST_INDEX(n); + result = *my_free_list; + if (result == 0) { + void *r = a -> refill(ROUND_UP(n)); + return r; + } + *my_free_list = result -> free_list_link; + return (result); + }; + + /* p may not be 0 */ + static void deallocate(void *p, size_t n) + { + obj *q = (obj *)p; + obj * volatile * my_free_list; + __pthread_alloc_template<dummy>* a; + + if (n > MAX_BYTES) { + free(p); + return; + } + if (!key_initialized || + !(a = (__pthread_alloc_template<dummy>*) + pthread_getspecific(key))) { + a = get_allocator_instance(); + } + my_free_list = a->free_list + FREELIST_INDEX(n); + q -> free_list_link = *my_free_list; + *my_free_list = q; + } + + static void * reallocate(void *p, size_t old_sz, size_t new_sz); + +} ; + +typedef __pthread_alloc_template<false> pthread_alloc; + + +template <bool dummy> +void __pthread_alloc_template<dummy>::destructor(void * instance) +{ + __pthread_alloc_template<dummy>* a = + (__pthread_alloc_template<dummy>*)instance; + a -> next = free_allocators; + free_allocators = a; +} + +template <bool dummy> +__pthread_alloc_template<dummy>* +__pthread_alloc_template<dummy>::new_allocator() +{ + if (0 != free_allocators) { + __pthread_alloc_template<dummy>* result = free_allocators; + free_allocators = free_allocators -> next; + return result; + } else { + return new __pthread_alloc_template<dummy>; + } +} + +template <bool dummy> +__pthread_alloc_template<dummy>* +__pthread_alloc_template<dummy>::get_allocator_instance() +{ + __pthread_alloc_template<dummy>* result; + if (!key_initialized) { + /*REFERENCED*/ + lock lock_instance; + if (!key_initialized) { + if (pthread_key_create(&key, destructor)) { + abort(); // failed + } + key_initialized = true; + } + } + result = new_allocator(); + if (pthread_setspecific(key, result)) abort(); + return result; +} + +/* We allocate memory in large chunks in order to avoid fragmenting */ +/* the malloc heap too much. */ +/* We assume that size is properly aligned. */ +template <bool dummy> +char *__pthread_alloc_template<dummy> +::chunk_alloc(size_t size, int &nobjs) +{ + { + char * result; + size_t total_bytes; + size_t bytes_left; + /*REFERENCED*/ + lock lock_instance; // Acquire lock for this routine + + total_bytes = size * nobjs; + bytes_left = end_free - start_free; + if (bytes_left >= total_bytes) { + result = start_free; + start_free += total_bytes; + return(result); + } else if (bytes_left >= size) { + nobjs = bytes_left/size; + total_bytes = size * nobjs; + result = start_free; + start_free += total_bytes; + return(result); + } else { + size_t bytes_to_get = 2 * total_bytes + ROUND_UP(heap_size >> 4); + // Try to make use of the left-over piece. + if (bytes_left > 0) { + __pthread_alloc_template<dummy>* a = + (__pthread_alloc_template<dummy>*)pthread_getspecific(key); + obj * volatile * my_free_list = + a->free_list + FREELIST_INDEX(bytes_left); + + ((obj *)start_free) -> free_list_link = *my_free_list; + *my_free_list = (obj *)start_free; + } +# ifdef _SGI_SOURCE + // Try to get memory that's aligned on something like a + // cache line boundary, so as to avoid parceling out + // parts of the same line to different threads and thus + // possibly different processors. + { + const int cache_line_size = 128; // probable upper bound + bytes_to_get &= ~(cache_line_size-1); + start_free = (char *)memalign(cache_line_size, bytes_to_get); + if (0 == start_free) { + start_free = (char *)malloc_alloc::allocate(bytes_to_get); + } + } +# else /* !SGI_SOURCE */ + start_free = (char *)malloc_alloc::allocate(bytes_to_get); +# endif + heap_size += bytes_to_get; + end_free = start_free + bytes_to_get; + } + } + // lock is released here + return(chunk_alloc(size, nobjs)); +} + + +/* Returns an object of size n, and optionally adds to size n free list.*/ +/* We assume that n is properly aligned. */ +/* We hold the allocation lock. */ +template <bool dummy> +void *__pthread_alloc_template<dummy> +::refill(size_t n) +{ + int nobjs = 128; + char * chunk = chunk_alloc(n, nobjs); + obj * volatile * my_free_list; + obj * result; + obj * current_obj, * next_obj; + int i; + + if (1 == nobjs) { + return(chunk); + } + my_free_list = free_list + FREELIST_INDEX(n); + + /* Build free list in chunk */ + result = (obj *)chunk; + *my_free_list = next_obj = (obj *)(chunk + n); + for (i = 1; ; i++) { + current_obj = next_obj; + next_obj = (obj *)((char *)next_obj + n); + if (nobjs - 1 == i) { + current_obj -> free_list_link = 0; + break; + } else { + current_obj -> free_list_link = next_obj; + } + } + return(result); +} + +template <bool dummy> +void *__pthread_alloc_template<dummy> +::reallocate(void *p, size_t old_sz, size_t new_sz) +{ + void * result; + size_t copy_sz; + + if (old_sz > MAX_BYTES && new_sz > MAX_BYTES) { + return(realloc(p, new_sz)); + } + if (ROUND_UP(old_sz) == ROUND_UP(new_sz)) return(p); + result = allocate(new_sz); + copy_sz = new_sz > old_sz? old_sz : new_sz; + memcpy(result, p, copy_sz); + deallocate(p, old_sz); + return(result); +} + +template <bool dummy> +__pthread_alloc_template<dummy> * +__pthread_alloc_template<dummy>::free_allocators = 0; + +template <bool dummy> +pthread_key_t __pthread_alloc_template<dummy>::key; + +template <bool dummy> +bool __pthread_alloc_template<dummy>::key_initialized = false; + +template <bool dummy> +pthread_mutex_t __pthread_alloc_template<dummy>::chunk_allocator_lock += PTHREAD_MUTEX_INITIALIZER; + +template <bool dummy> +char *__pthread_alloc_template<dummy> +::start_free = 0; + +template <bool dummy> +char *__pthread_alloc_template<dummy> +::end_free = 0; + +template <bool dummy> +size_t __pthread_alloc_template<dummy> +::heap_size = 0; + + +#endif /* __NODE_ALLOC_H */ diff --git a/libstdc++/stl/rope.h b/libstdc++/stl/rope.h new file mode 100644 index 0000000..105eb05 --- /dev/null +++ b/libstdc++/stl/rope.h @@ -0,0 +1,2055 @@ +/* + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#ifndef _ROPE_H +# define _ROPE_H + +# include <iterator.h> +# include <algobase.h> +# include <algo.h> +# include <function.h> +# include <stddef.h> +# include <alloc.h> +# include <hashtable.h> +# ifdef __GC +# define __GC_CONST const +# else +# define __GC_CONST // constant except for deallocation +# endif +# ifdef __STL_SGI_THREADS +# include <mutex.h> +# endif + +// The end-of-C-string character. +// This is what the draft standard says it should be. +template <class charT> +inline charT __eos(charT*) { return charT(); } + +// Test for basic character types. +// For basic character types leaves having a trailing eos. +template <class charT> +inline bool __is_basic_char_type(charT* c) { return false; } +template <class charT> +inline bool __is_one_byte_char_type(charT* c) { return false; } + +inline bool __is_basic_char_type(char* c) { return true; } +inline bool __is_one_byte_char_type(char* c) { return true; } +inline bool __is_basic_char_type(wchar_t* c) { return true; } + +// Store an eos iff charT is a basic character type. +// Do not reference __eos if it isn't. +template <class charT> +inline void __cond_store_eos(charT& c) {} + +inline void __cond_store_eos(char& c) { c = 0; } +inline void __cond_store_eos(wchar_t& c) { c = 0; } + + +// rope<charT,Alloc> is a sequence of charT. +// Ropes appear to be mutable, but update operations +// really copy enough of the data structure to leave the original +// valid. Thus ropes can be logically copied by just copying +// a pointer value. +// The __eos function is used for those functions that +// convert to/from C-like strings to detect the end of the string. +// __compare is used as the character comparison function. +template <class charT> +class char_producer { + public: + virtual ~char_producer() {}; + virtual void operator()(size_t start_pos, size_t len, charT* buffer) + = 0; + // Buffer should really be an arbitrary output iterator. + // That way we could flatten directly into an ostream, etc. + // This is thoroughly impossible, since iterator types don't + // have runtime descriptions. +}; + +// Sequence buffers: +// +// Sequence must provide an append operation that appends an +// array to the sequence. Sequence buffers are useful only if +// appending an entire array is cheaper than appending element by element. +// This is true for many string representations. +// This should perhaps inherit from ostream<sequence::value_type> +// and be implemented correspondingly, so that they can be used +// for formatted. For the sake of portability, we don't do this yet. +// +// For now, sequence buffers behave as output iterators. But they also +// behave a little like basic_ostringstream<sequence::value_type> and a +// little like containers. + +template<class sequence, size_t buf_sz = 100 +# if defined(__sgi) && !defined(__GNUC__) +# define __TYPEDEF_WORKAROUND + ,class v = typename sequence::value_type +# endif + > +// The 3rd parameter works around a common compiler bug. +class sequence_buffer : public output_iterator { + public: +# ifndef __TYPEDEF_WORKAROUND + typedef typename sequence::value_type value_type; +# else + typedef v value_type; +# endif + protected: + sequence *prefix; + value_type buffer[buf_sz]; + size_t buf_count; + public: + void flush() { + prefix->append(buffer, buffer + buf_count); + buf_count = 0; + } + ~sequence_buffer() { flush(); } + sequence_buffer() : prefix(0), buf_count(0) {} + sequence_buffer(const sequence_buffer & x) { + prefix = x.prefix; + buf_count = x.buf_count; + copy(x.buffer, x.buffer + x.buf_count, buffer); + } + sequence_buffer(sequence_buffer & x) { + x.flush(); + prefix = x.prefix; + buf_count = 0; + } + sequence_buffer(sequence& s) : prefix(&s), buf_count(0) {} + sequence_buffer& operator= (sequence_buffer& x) { + x.flush(); + prefix = x.prefix; + buf_count = 0; + return *this; + } + sequence_buffer& operator= (const sequence_buffer& x) { + prefix = x.prefix; + buf_count = x.buf_count; + copy(x.buffer, x.buffer + x.buf_count, buffer); + return *this; + } + void push_back(value_type x) + { + if (buf_count < buf_sz) { + buffer[buf_count] = x; + ++buf_count; + } else { + flush(); + buffer[0] = x; + buf_count = 1; + } + } + void append(value_type *s, size_t len) + { + if (len + buf_count <= buf_sz) { + size_t i, j; + for (i = buf_count, j = 0; j < len; i++, j++) { + buffer[i] = s[j]; + } + buf_count += len; + } else if (0 == buf_count) { + prefix->append(s, s + len); + } else { + flush(); + append(s, len); + } + } + sequence_buffer& write(value_type *s, size_t len) + { + append(s, len); + return *this; + } + sequence_buffer& put(value_type x) + { + push_back(x); + return *this; + } + sequence_buffer& operator=(const value_type& rhs) + { + push_back(rhs); + return *this; + } + sequence_buffer& operator*() { return *this; } + sequence_buffer& operator++() { return *this; } + sequence_buffer& operator++(int) { return *this; } +}; + +// The following should be treated as private, at least for now. +template<class charT> +class __rope_char_consumer { + public: + // If we had member templates, these should not be virtual. + // For now we need to use run-time parametrization where + // compile-time would do. Hence this should all be private + // for now. + // The symmetry with char_producer is accidental and temporary. + virtual ~__rope_char_consumer() {}; + virtual bool operator()(const charT* buffer, size_t len) = 0; +}; + +// +// What follows should really be local to rope. Unfortunately, +// that doesn't work, since it makes it impossible to define generic +// equality on rope iterators. According to the draft standard, the +// template parameters for such an equality operator cannot be inferred +// from the occurence of a member class as a parameter. +// (SGI compilers in fact allow this, but the result wouldn't be +// portable.) +// Similarly, some of the static member functions are member functions +// only to avoid polluting the global namespace, and to circumvent +// restrictions on type inference for template functions. +// + +template<class CharT, class Alloc=__ALLOC> class rope; +template<class CharT, class Alloc> struct __rope_RopeConcatenation; +template<class CharT, class Alloc> struct __rope_RopeLeaf; +template<class CharT, class Alloc> struct __rope_RopeFunction; +template<class CharT, class Alloc> struct __rope_RopeSubstring; +template<class CharT, class Alloc> class __rope_iterator; +template<class CharT, class Alloc> class __rope_const_iterator; +template<class CharT, class Alloc> class __rope_charT_ref_proxy; +template<class CharT, class Alloc> class __rope_charT_ptr_proxy; + +// +// The internal data structure for representing a rope. This is +// private to the implementation. A rope is really just a pointer +// to one of these. +// +// A few basic functions for manipulating this data structure +// are members of RopeBase. Most of the more complex algorithms +// are implemented as rope members. +// +// Some of the static member functions of RopeBase have identically +// named functions in rope that simply invoke the RopeBase versions. +// + +template<class charT, class Alloc> +struct __rope_RopeBase { + typedef rope<charT,Alloc> my_rope; + typedef simple_alloc<__rope_RopeConcatenation<charT,Alloc>, Alloc> CAlloc; + typedef simple_alloc<__rope_RopeLeaf<charT,Alloc>, Alloc> LAlloc; + typedef simple_alloc<__rope_RopeFunction<charT,Alloc>, Alloc> FAlloc; + typedef simple_alloc<__rope_RopeSubstring<charT,Alloc>, Alloc> SAlloc; + public: + enum { max_rope_depth = 45 }; + enum {leaf, concat, substringfn, function} tag:8; + bool is_balanced:8; + unsigned char depth; + size_t size; + __GC_CONST charT * c_string; + /* Flattened version of string, if needed. */ + /* typically 0. */ + /* If it's not 0, then the memory is owned */ + /* by this node. */ + /* In the case of a leaf, this may point to */ + /* the same memory as the data field. */ +# ifndef __GC +# if defined(__STL_WIN32THREADS) + long refcount; // InterlockedIncrement wants a long * +# else + size_t refcount; +# endif + // We count references from rope instances + // and references from other rope nodes. We + // do not count const_iterator references. + // Iterator references are counted so that rope modifications + // can be detected after the fact. + // Generally function results are counted, i.e. + // a pointer returned by a function is included at the + // point at which the pointer is returned. + // The recipient should decrement the count if the + // result is not needed. + // Generally function arguments are not reflected + // in the reference count. The callee should increment + // the count before saving the argument someplace that + // will outlive the call. +# endif +# ifndef __GC +# ifdef __STL_SGI_THREADS + // Reference counting with multiple threads and no + // hardware or thread package support is pretty awful. + // Mutexes are normally too expensive. + // We'll assume a COMPARE_AND_SWAP(destp, old, new) + // operation, which might be cheaper. +# if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) +# define __add_and_fetch(l,v) add_then_test((unsigned long *)l,v) +# endif + void init_refcount_lock() {} + void incr_refcount () + { + __add_and_fetch(&refcount, 1); + } + size_t decr_refcount () + { + return __add_and_fetch(&refcount, (size_t)(-1)); + } +# elif defined(__STL_WIN32THREADS) + void init_refcount_lock() {} + void incr_refcount () + { + InterlockedIncrement(&refcount); + } + size_t decr_refcount () + { + return InterlockedDecrement(&refcount); + } +# elif defined(_PTHREADS) + // This should be portable, but performance is expected + // to be quite awful. This really needs platform specific + // code. + pthread_mutex_t refcount_lock; + void init_refcount_lock() { + pthread_mutex_init(&refcount_lock, 0); + } + void incr_refcount () + { + pthread_mutex_lock(&refcount_lock); + ++refcount; + pthread_mutex_unlock(&refcount_lock); + } + size_t decr_refcount () + { + size_t result; + pthread_mutex_lock(&refcount_lock); + result = --refcount; + pthread_mutex_unlock(&refcount_lock); + return result; + } +# else + void init_refcount_lock() {} + void incr_refcount () + { + ++refcount; + } + size_t decr_refcount () + { + --refcount; + return refcount; + } +# endif +# else + void incr_refcount () {} +# endif + static void free_string(charT *, size_t len); + // Deallocate data section of a leaf. + // This shouldn't be a member function. + // But its hard to do anything else at the + // moment, because it's templatized w.r.t. + // an allocator. + // Does nothing if __GC is defined. +# ifndef __GC + void free_c_string(); + void free_tree(); + // Deallocate t. Assumes t is not 0. + void unref_nonnil() + { + if (0 == decr_refcount()) free_tree(); + } + void ref_nonnil() + { + incr_refcount(); + } + static void unref(__rope_RopeBase* t) + { + if (0 != t) { + t -> unref_nonnil(); + } + } + static void ref(__rope_RopeBase* t) + { + if (0 != t) t -> incr_refcount(); + } +# else /* __GC */ + void unref_nonnil() {} + void ref_nonnil() {} + static void unref(__rope_RopeBase* t) {} + static void ref(__rope_RopeBase* t) {} + static void fn_finalization_proc(void * tree, void *); +# endif + + // The data fields of leaves are allocated with some + // extra space, to accomodate future growth and for basic + // character types, to hold a trailing eos character. + enum { alloc_granularity = 8 }; + static size_t rounded_up_size(size_t n) { + size_t size_with_eos; + + if (__is_basic_char_type((charT *)0)) { + size_with_eos = (n + 1) * sizeof(charT); + } else { + size_with_eos = n * sizeof(charT); + } +# ifdef __GC + return size_with_eos; +# else + // Allow slop for in-place expansion. + return (size_with_eos + alloc_granularity-1) + &~ (alloc_granularity-1); +# endif + } +}; + +template<class charT, class Alloc> +struct __rope_RopeLeaf : public __rope_RopeBase<charT,Alloc> { + public: // Apparently needed by VC++ + __GC_CONST charT* data; /* Not necessarily 0 terminated. */ + /* The allocated size is */ + /* rounded_up_size(size), except */ + /* in the GC case, in which it */ + /* doesn't matter. */ +}; + +template<class charT, class Alloc> +struct __rope_RopeConcatenation : public __rope_RopeBase<charT,Alloc> { + public: + __rope_RopeBase<charT,Alloc>* left; + __rope_RopeBase<charT,Alloc>* right; +}; + +template<class charT, class Alloc> +struct __rope_RopeFunction : public __rope_RopeBase<charT,Alloc> { + public: + char_producer<charT>* fn; +# ifndef __GC + bool delete_when_done; // Char_producer is owned by the + // rope and should be explicitly + // deleted when the rope becomes + // inaccessible. +# else + // In the GC case, we either register the rope for + // finalization, or not. Thus the field is unnecessary; + // the information is stored in the collector data structures. +# endif +}; +// Substring results are usually represented using just +// concatenation nodes. But in the case of very long flat ropes +// or ropes with a functional representation that isn't practical. +// In that case, we represent the result as a special case of +// RopeFunction, whose char_producer points back to the rope itself. +// In all cases except repeated substring operations and +// deallocation, we treat the result as a RopeFunction. +template<class charT, class Alloc> +struct __rope_RopeSubstring: public __rope_RopeFunction<charT,Alloc>, + public char_producer<charT> { + public: + __rope_RopeBase<charT,Alloc> * base; // not 0 + size_t start; + virtual ~__rope_RopeSubstring() {} + virtual void operator()(size_t start_pos, size_t req_len, + charT *buffer) { + switch(base -> tag) { + case function: + case substringfn: + { + char_producer<charT> *fn = + ((__rope_RopeFunction<charT,Alloc> *)base) -> fn; + __stl_assert(start_pos + req_len <= size); + __stl_assert(start + size <= base -> size); + (*fn)(start_pos + start, req_len, buffer); + } + break; + case leaf: + { + __GC_CONST charT * s = + ((__rope_RopeLeaf<charT,Alloc> *)base) -> data; + uninitialized_copy_n(s + start_pos + start, req_len, + buffer); + } + break; + default: + __stl_assert(false); + } + } + __rope_RopeSubstring(__rope_RopeBase<charT,Alloc> * b, size_t s, size_t l) : + base(b), start(s) { +# ifndef __GC + refcount = 1; + init_refcount_lock(); + base -> ref_nonnil(); +# endif + size = l; + tag = substringfn; + depth = 0; + c_string = 0; + fn = this; + } +}; + + +// Self-destructing pointers to RopeBase. +// These are not conventional smart pointers. Their +// only purpose in life is to ensure that unref is called +// on the pointer either at normal exit or if an exception +// is raised. It is the caller's responsibility to +// adjust reference counts when these pointers are initialized +// or assigned to. (This convention significantly reduces +// the number of potentially expensive reference count +// updates.) +#ifndef __GC + template<class charT, class Alloc> + struct __rope_self_destruct_ptr { + __rope_RopeBase<charT,Alloc> * ptr; + ~__rope_self_destruct_ptr() { __rope_RopeBase<charT,Alloc>::unref(ptr); } +# ifdef __STL_USE_EXCEPTIONS + __rope_self_destruct_ptr() : ptr(0) {}; +# else + __rope_self_destruct_ptr() {}; +# endif + __rope_self_destruct_ptr(__rope_RopeBase<charT,Alloc> * p) : ptr(p) {} + __rope_RopeBase<charT,Alloc> & operator*() { return *ptr; } + __rope_RopeBase<charT,Alloc> * operator->() { return ptr; } + operator __rope_RopeBase<charT,Alloc> *() { return ptr; } + __rope_self_destruct_ptr & operator= (__rope_RopeBase<charT,Alloc> * x) + { ptr = x; return *this; } + }; +#endif + +// unwind-protect +# ifdef __STL_USE_EXCEPTIONS +# define __STL_TRY try { +# define __STL_UNWIND(action) } catch(...) { action; throw; } +# define __STL_ALWAYS(action) action; } catch(...) { action; throw; } +# else +# define __STL_TRY { +# define __STL_UNWIND(action) } +# define __STL_ALWAYS(action) action; } +# endif +// Dereferencing a nonconst iterator has to return something +// that behaves almost like a reference. It's not possible to +// return an actual reference since assignment requires extra +// work. And we would get into the same problems as with the +// CD2 version of basic_string. +template<class charT, class Alloc> +class __rope_charT_ref_proxy { + friend class rope<charT,Alloc>; + friend class __rope_iterator<charT,Alloc>; + friend class __rope_charT_ptr_proxy<charT,Alloc>; +# ifdef __GC + typedef __rope_RopeBase<charT,Alloc> * self_destruct_ptr; +# else + typedef __rope_self_destruct_ptr<charT,Alloc> self_destruct_ptr; +# endif + typedef __rope_RopeBase<charT,Alloc> RopeBase; + typedef rope<charT,Alloc> my_rope; + size_t pos; + charT current; + bool current_valid; + my_rope * root; // The whole rope. + public: + __rope_charT_ref_proxy(my_rope * r, size_t p) : + pos(p), root(r), current_valid(false) {} + __rope_charT_ref_proxy(my_rope * r, size_t p, + charT c) : + pos(p), root(r), current(c), current_valid(true) {} + operator charT () const; + __rope_charT_ref_proxy& operator= (charT c); + __rope_charT_ptr_proxy<charT,Alloc> operator& () const; + __rope_charT_ref_proxy& operator= (const __rope_charT_ref_proxy& c) { + return operator=((charT)c); + } +}; + +template<class charT, class Alloc> +class __rope_charT_ptr_proxy { + friend class __rope_charT_ref_proxy<charT,Alloc>; + size_t pos; + charT current; + bool current_valid; + rope<charT,Alloc> * root; // The whole rope. + public: + __rope_charT_ptr_proxy(const __rope_charT_ref_proxy<charT,Alloc> & x) : + pos(x.pos), root(x.root), current_valid(x.current_valid), + current(x.current) {} + __rope_charT_ptr_proxy(const __rope_charT_ptr_proxy & x) : + pos(x.pos), root(x.root), current_valid(x.current_valid), + current(x.current) {} + __rope_charT_ptr_proxy() {} + __rope_charT_ptr_proxy(charT * x) : root(0), pos(0) { + __stl_assert(0 == x); + } + __rope_charT_ptr_proxy& operator= (const __rope_charT_ptr_proxy& x) { + pos = x.pos; + current = x.current; + current_valid = x.current_valid; + root = x.root; + return *this; + } + friend bool operator== + (const __rope_charT_ptr_proxy<charT,Alloc> & x, + const __rope_charT_ptr_proxy<charT,Alloc> & y); + __rope_charT_ref_proxy<charT,Alloc> operator *() const { + if (current_valid) { + return __rope_charT_ref_proxy<charT,Alloc>(root, pos, current); + } else { + return __rope_charT_ref_proxy<charT,Alloc>(root, pos); + } + } +}; + +// Rope iterators: +// Unlike in the C version, we cache only part of the stack +// for rope iterators, since they must be efficiently copyable. +// When we run out of cache, we have to reconstruct the iterator +// value. +// Pointers from iterators are not included in reference counts. +// Iterators are assumed to be thread private. Ropes can +// be shared. + +template<class charT, class Alloc> +class __rope_iterator_base: + public random_access_iterator<charT, ptrdiff_t> { + friend class rope<charT, Alloc>; + public: + typedef __rope_RopeBase<charT,Alloc> RopeBase; + // Borland doesnt want this to be protected. + protected: + enum { path_cache_len = 4 }; // Must be <= 9. + enum { iterator_buf_len = 15 }; + size_t current_pos; + RopeBase * root; // The whole rope. + size_t leaf_pos; // Starting position for current leaf + __GC_CONST charT * buf_start; + // Buffer possibly + // containing current char. + __GC_CONST charT * buf_ptr; + // Pointer to current char in buffer. + // != 0 ==> buffer valid. + __GC_CONST charT * buf_end; + // One past last valid char in buffer. + // What follows is the path cache. We go out of our + // way to make this compact. + // Path_end contains the bottom section of the path from + // the root to the current leaf. + const RopeBase * path_end[path_cache_len]; + int leaf_index; // Last valid pos in path_end; + // path_end[0] ... path_end[leaf_index-1] + // point to concatenation nodes. + unsigned char path_directions; + // (path_directions >> i) & 1 is 1 + // iff we got from path_end[leaf_index - i - 1] + // to path_end[leaf_index - i] by going to the + // right. Assumes path_cache_len <= 9. + charT tmp_buf[iterator_buf_len]; + // Short buffer for surrounding chars. + // This is useful primarily for + // RopeFunctions. We put the buffer + // here to avoid locking in the + // multithreaded case. + // The cached path is generally assumed to be valid + // only if the buffer is valid. + static void setbuf(__rope_iterator_base &x); + // Set buffer contents given + // path cache. + static void setcache(__rope_iterator_base &x); + // Set buffer contents and + // path cache. + static void setcache_for_incr(__rope_iterator_base &x); + // As above, but assumes path + // cache is valid for previous posn. + __rope_iterator_base() {} + __rope_iterator_base(RopeBase * root, size_t pos): + root(root), current_pos(pos), buf_ptr(0) {} + __rope_iterator_base(const __rope_iterator_base& x) { + if (0 != x.buf_ptr) { + *this = x; + } else { + current_pos = x.current_pos; + root = x.root; + buf_ptr = 0; + } + } + void incr(size_t n); + void decr(size_t n); + public: + size_t index() const { return current_pos; } +}; + +template<class charT, class Alloc> class __rope_iterator; + +template<class charT, class Alloc> +class __rope_const_iterator : public __rope_iterator_base<charT,Alloc> { + friend class rope<charT,Alloc>; + protected: + __rope_const_iterator(const RopeBase * root, size_t pos): + __rope_iterator_base<charT,Alloc>( + const_cast<RopeBase *>(root), pos) + // Only nonconst iterators modify root ref count + {} + + public: + __rope_const_iterator() {}; + __rope_const_iterator(const __rope_const_iterator & x) : + __rope_iterator_base<charT,Alloc>(x) { } + __rope_const_iterator(const __rope_iterator<charT,Alloc> & x); + __rope_const_iterator(const rope<charT,Alloc> &r, size_t pos) : + __rope_iterator_base<charT,Alloc>(r.tree_ptr, pos) {} + __rope_const_iterator& operator= (const __rope_const_iterator & x) { + if (0 != x.buf_ptr) { + *this = x; + } else { + current_pos = x.current_pos; + root = x.root; + buf_ptr = 0; + } + return(*this); + } + const charT& operator*() { + if (0 == buf_ptr) setcache(*this); + return *buf_ptr; + } + __rope_const_iterator& operator++() { + __GC_CONST charT * next; + if (0 != buf_ptr && (next = buf_ptr + 1) < buf_end) { + buf_ptr = next; + ++current_pos; + } else { + incr(1); + } + return *this; + } + __rope_const_iterator& operator+=(ptrdiff_t n) { + if (n >= 0) { + incr(n); + } else { + decr(-n); + } + return *this; + } + __rope_const_iterator& operator--() { + decr(1); + return *this; + } + __rope_const_iterator& operator-=(ptrdiff_t n) { + if (n >= 0) { + decr(n); + } else { + incr(-n); + } + return *this; + } + __rope_const_iterator operator++(int) { + size_t old_pos = current_pos; + incr(1); + return __rope_const_iterator<charT,Alloc>(root, old_pos); + // This makes a subsequent dereference expensive. + // Perhaps we should instead copy the iterator + // if it has a valid cache? + } + __rope_const_iterator operator--(int) { + size_t old_pos = current_pos; + decr(1); + return __rope_const_iterator<charT,Alloc>(root, old_pos); + } + friend __rope_const_iterator<charT,Alloc> operator- + (const __rope_const_iterator<charT,Alloc> & x, + ptrdiff_t n); + friend __rope_const_iterator<charT,Alloc> operator+ + (const __rope_const_iterator<charT,Alloc> & x, + ptrdiff_t n); + friend __rope_const_iterator<charT,Alloc> operator+ + (ptrdiff_t n, + const __rope_const_iterator<charT,Alloc> & x); + charT operator[](size_t n) { + return rope<charT,Alloc>::fetch(root, current_pos + n); + } + friend bool operator== + (const __rope_const_iterator<charT,Alloc> & x, + const __rope_const_iterator<charT,Alloc> & y); + friend bool operator< + (const __rope_const_iterator<charT,Alloc> & x, + const __rope_const_iterator<charT,Alloc> & y); + friend ptrdiff_t operator- + (const __rope_const_iterator<charT,Alloc> & x, + const __rope_const_iterator<charT,Alloc> & y); +}; + +template<class charT, class Alloc> +class __rope_iterator : public __rope_iterator_base<charT,Alloc> { + friend class rope<charT,Alloc>; + protected: + rope<charT,Alloc> * root_rope; + // root is treated as a cached version of this, + // and is used to detect changes to the underlying + // rope. + // Root is included in the reference count. + // This is necessary so that we can detect changes reliably. + // Unfortunately, it requires careful bookkeeping for the + // nonGC case. + __rope_iterator(rope<charT,Alloc> * r, size_t pos): + __rope_iterator_base<charT,Alloc>(r -> tree_ptr, pos), + root_rope(r) { + RopeBase::ref(root); + } + void check(); + public: + rope<charT,Alloc>& container() { return *root_rope; } + __rope_iterator() { + root = 0; // Needed for reference counting. + }; + __rope_iterator(const __rope_iterator & x) : + __rope_iterator_base<charT,Alloc>(x) { + root_rope = x.root_rope; + RopeBase::ref(root); + } + __rope_iterator(rope<charT,Alloc>& r, size_t pos); + ~__rope_iterator() { + RopeBase::unref(root); + } + __rope_iterator& operator= (const __rope_iterator & x) { + RopeBase *old = root; + + RopeBase::ref(x.root); + if (0 != x.buf_ptr) { + *this = x; + } else { + current_pos = x.current_pos; + root = x.root; + root_rope = x.root_rope; + buf_ptr = 0; + } + RopeBase::unref(old); + return(*this); + } + __rope_charT_ref_proxy<charT,Alloc> operator*() { + check(); + if (0 == buf_ptr) { + return __rope_charT_ref_proxy<charT,Alloc>(root_rope, current_pos); + } else { + return __rope_charT_ref_proxy<charT,Alloc>(root_rope, + current_pos, *buf_ptr); + } + } + __rope_iterator& operator++() { + incr(1); + return *this; + } + __rope_iterator& operator+=(difference_type n) { + if (n >= 0) { + incr(n); + } else { + decr(-n); + } + return *this; + } + __rope_iterator& operator--() { + decr(1); + return *this; + } + __rope_iterator& operator-=(difference_type n) { + if (n >= 0) { + decr(n); + } else { + incr(-n); + } + return *this; + } + __rope_iterator operator++(int) { + size_t old_pos = current_pos; + incr(1); + return __rope_iterator<charT,Alloc>(root_rope, old_pos); + } + __rope_iterator operator--(int) { + size_t old_pos = current_pos; + decr(1); + return __rope_iterator<charT,Alloc>(root_rope, old_pos); + } + __rope_charT_ref_proxy<charT,Alloc> operator[](ptrdiff_t n) { + return __rope_charT_ref_proxy<charT,Alloc>(root_rope, current_pos + n); + } + friend bool operator== + (const __rope_iterator<charT,Alloc> & x, + const __rope_iterator<charT,Alloc> & y); + friend bool operator< + (const __rope_iterator<charT,Alloc> & x, + const __rope_iterator<charT,Alloc> & y); + friend ptrdiff_t operator- + (const __rope_iterator<charT,Alloc> & x, + const __rope_iterator<charT,Alloc> & y); + friend __rope_iterator<charT,Alloc> operator- + (const __rope_iterator<charT,Alloc> & x, + ptrdiff_t n); + friend __rope_iterator<charT,Alloc> operator+ + (const __rope_iterator<charT,Alloc> & x, + ptrdiff_t n); + friend __rope_iterator<charT,Alloc> operator+ + (ptrdiff_t n, + const __rope_iterator<charT,Alloc> & x); + +}; + +template <class charT, class Alloc> +class rope { + public: + typedef charT value_type; + typedef ptrdiff_t difference_type; + typedef size_t size_type; + typedef const charT& const_reference; + typedef const charT* const_pointer; + typedef __rope_iterator<charT,Alloc> iterator; + typedef __rope_const_iterator<charT,Alloc> const_iterator; + typedef __rope_charT_ref_proxy<charT,Alloc> reference; + typedef __rope_charT_ptr_proxy<charT,Alloc> pointer; + + friend class __rope_iterator<charT,Alloc>; + friend class __rope_const_iterator<charT,Alloc>; + friend struct __rope_RopeBase<charT,Alloc>; + friend class __rope_iterator_base<charT,Alloc>; + friend class __rope_charT_ptr_proxy<charT,Alloc>; + friend class __rope_charT_ref_proxy<charT,Alloc>; + friend struct __rope_RopeSubstring<charT,Alloc>; + + protected: + typedef __GC_CONST charT * cstrptr; +# ifdef __STL_SGI_THREADS + static cstrptr atomic_swap(cstrptr *p, cstrptr q) { +# if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) + return (cstrptr) test_and_set((unsigned long *)p, + (unsigned long)q); +# else + return (cstrptr) __test_and_set((unsigned long *)p, + (unsigned long)q); +# endif + } +# elif defined(__STL_WIN32THREADS) + static cstrptr atomic_swap(cstrptr *p, cstrptr q) { + return (cstrptr) InterlockedExchange((LPLONG)p, (LONG)q); + } +# elif defined(_PTHREADS) + // This should be portable, but performance is expected + // to be quite awful. This really needs platform specific + // code. + static pthread_mutex_t swap_lock; + static cstrptr atomic_swap(cstrptr *p, cstrptr q) { + pthread_mutex_lock(&swap_lock); + cstrptr result = *p; + *p = q; + pthread_mutex_unlock(&swap_lock); + return result; + } +# else + static cstrptr atomic_swap(cstrptr *p, cstrptr q) { + cstrptr result = *p; + *p = q; + return result; + } +# endif + + static charT empty_c_str[1]; + + typedef simple_alloc<__rope_RopeConcatenation<charT,Alloc>, Alloc> CAlloc; + typedef simple_alloc<__rope_RopeLeaf<charT,Alloc>, Alloc> LAlloc; + typedef simple_alloc<__rope_RopeFunction<charT,Alloc>, Alloc> FAlloc; + typedef simple_alloc<__rope_RopeSubstring<charT,Alloc>, Alloc> SAlloc; + static bool is0(charT c) { return c == __eos((charT *)0); } + enum { copy_max = 23 }; + // For strings shorter than copy_max, we copy to + // concatenate. + + typedef __rope_RopeBase<charT,Alloc> RopeBase; + typedef __rope_RopeConcatenation<charT,Alloc> RopeConcatenation; + typedef __rope_RopeLeaf<charT,Alloc> RopeLeaf; + typedef __rope_RopeFunction<charT,Alloc> RopeFunction; + typedef __rope_RopeSubstring<charT,Alloc> RopeSubstring; + + // The only data member of a rope: + RopeBase *tree_ptr; + + // Retrieve a character at the indicated position. + static charT fetch(RopeBase * r, size_type pos); + +# ifndef __GC + // Obtain a pointer to the character at the indicated position. + // The pointer can be used to change the character. + // If such a pointer cannot be produced, as is frequently the + // case, 0 is returned instead. + // (Returns nonzero only if all nodes in the path have a refcount + // of 1.) + static charT * fetch_ptr(RopeBase * r, size_type pos); +# endif + + static bool apply_to_pieces( + // should be template parameter + __rope_char_consumer<charT>& c, + const RopeBase * r, + size_t begin, size_t end); + // begin and end are assumed to be in range. + +# ifndef __GC + static void unref(RopeBase* t) + { + RopeBase::unref(t); + } + static void ref(RopeBase* t) + { + RopeBase::ref(t); + } +# else /* __GC */ + static void unref(RopeBase* t) {} + static void ref(RopeBase* t) {} +# endif + + +# ifdef __GC + typedef __rope_RopeBase<charT,Alloc> * self_destruct_ptr; +# else + typedef __rope_self_destruct_ptr<charT,Alloc> self_destruct_ptr; +# endif + + // Result is counted in refcount. + static RopeBase * substring(RopeBase * base, + size_t start, size_t endp1); + + static RopeBase * concat_char_iter(RopeBase * r, + const charT *iter, size_t slen); + // Concatenate rope and char ptr, copying s. + // Should really take an arbitrary iterator. + // Result is counted in refcount. + static RopeBase * destr_concat_char_iter(RopeBase * r, + const charT *iter, size_t slen) + // As above, but one reference to r is about to be + // destroyed. Thus the pieces may be recycled if all + // relevent reference counts are 1. +# ifdef __GC + // We can't really do anything since refcounts are unavailable. + { return concat_char_iter(r, iter, slen); } +# else + ; +# endif + + static RopeBase * concat(RopeBase *left, RopeBase *right); + // General concatenation on RopeBase. Result + // has refcount of 1. Adjusts argument refcounts. + + public: + void apply_to_pieces( size_t begin, size_t end, + __rope_char_consumer<charT>& c) const { + apply_to_pieces(c, tree_ptr, begin, end); + } + + + protected: + + static size_t rounded_up_size(size_t n) { + return RopeBase::rounded_up_size(n); + } + + static size_t allocated_capacity(size_t n) { + if (__is_basic_char_type((charT *)0)) { + return rounded_up_size(n) - 1; + } else { + return rounded_up_size(n); + } + } + + // s should really be an arbitrary input iterator. + // Adds a trailing NULL for basic char types. + static charT * alloc_copy(const charT *s, size_t size) + { + charT * result = (charT *) + Alloc::allocate(rounded_up_size(size)); + + uninitialized_copy_n(s, size, result); + __cond_store_eos(result[size]); + return(result); + } + + // Basic constructors for rope tree nodes. + // These return tree nodes with a 0 reference count. + static RopeLeaf * RopeLeaf_from_char_ptr(__GC_CONST charT *s, + size_t size); + // Takes ownership of its argument. + // Result has refcount 1. + // In the nonGC, basic_char_type case it assumes that s + // is eos-terminated. + // In the nonGC case, it was allocated from Alloc with + // rounded_up_size(size). + + // Concatenation of nonempty strings. + // Always builds a concatenation node. + // Rebalances if the result is too deep. + // Result has refcount 1. + // Does not increment left and right ref counts even though + // they are referenced. + static RopeBase * tree_concat(RopeBase * left, RopeBase * right); + + // Result has refcount 1. + // If delete_fn is true, then fn is deleted when the rope + // becomes inaccessible. + static RopeFunction * RopeFunction_from_fn + (char_producer<charT> *fn, size_t size, + bool delete_fn); + + // Concatenation helper functions + static RopeLeaf * leaf_concat_char_iter + (RopeLeaf * r, const charT * iter, size_t slen); + // Concatenate by copying leaf. + // should take an arbitrary iterator + // result has refcount 1. +# ifndef __GC + static RopeLeaf * destr_leaf_concat_char_iter + (RopeLeaf * r, const charT * iter, size_t slen); + // A version that potentially clobbers r if r -> refcount == 1. +# endif + + // A helper function for exponentiating strings. + // This uses a nonstandard refcount convention. + // The result has refcount 0. + struct concat_fn; + friend struct rope<charT,Alloc>::concat_fn; + + struct concat_fn + : binary_function<RopeBase *, RopeBase *, RopeBase *> { + RopeBase * operator() (RopeBase * x, RopeBase *y) { + RopeBase * result; + x -> ref_nonnil(); + y -> ref_nonnil(); + __STL_TRY + result = tree_concat(x, y); +# ifndef __GC + result -> refcount = 0; +# endif + __STL_UNWIND(unref(x); unref(y)); + return result; + // In the nonGC case, x and y must remain accessible through + // the result. Use of concat could result on a memory leak. + } + }; + + friend RopeBase* identity_element(concat_fn) { return 0; } + + static size_t char_ptr_len(const charT * s); + // slightly generalized strlen + + rope(RopeBase *t) : tree_ptr(t) { } + + + // Copy r to the CharT buffer. + // Returns buffer + r -> size. + // Assumes that buffer is uninitialized. + static charT * flatten(RopeBase * r, charT * buffer); + + // Again, with explicit starting position and length. + // Assumes that buffer is uninitialized. + static charT * flatten(RopeBase * r, + size_t start, size_t len, + charT * buffer); + + static const unsigned long min_len[RopeBase::max_rope_depth + 1]; + + static bool is_balanced(RopeBase *r) + { return (r -> size >= min_len[r -> depth]); } + + static bool is_almost_balanced(RopeBase *r) + { return (r -> depth == 0 || + r -> size >= min_len[r -> depth - 1]); } + + static bool is_roughly_balanced(RopeBase *r) + { return (r -> depth <= 1 || + r -> size >= min_len[r -> depth - 2]); } + + // Assumes the result is not empty. + static RopeBase * concat_and_set_balanced(RopeBase *left, + RopeBase *right) + { + RopeBase * result = concat(left, right); + if (is_balanced(result)) result -> is_balanced = true; + return result; + } + + // The basic rebalancing operation. Logically copies the + // rope. The result has refcount of 1. The client will + // usually decrement the reference count of r. + // The result isd within height 2 of balanced by the above + // definition. + static RopeBase * balance(RopeBase * r); + + // Add all unbalanced subtrees to the forest of balanceed trees. + // Used only by balance. + static void add_to_forest(RopeBase *r, RopeBase **forest); + + // Add r to forest, assuming r is already balanced. + static void add_leaf_to_forest(RopeBase *r, RopeBase **forest); + + // Print to stdout, exposing structure + static void dump(RopeBase * r, int indent = 0); + + // Return -1, 0, or 1 if x < y, x == y, or x > y resp. + static int compare(const RopeBase *x, const RopeBase *y); + + public: + bool empty() const { return 0 == tree_ptr; } + + // Comparison member function. This is public only for those + // clients that need a ternary comparison. Others + // should use the comparison operators below. + int compare(const rope &y) const { + return compare(tree_ptr, y.tree_ptr); + } + + rope(const charT *s) + { + size_t len = char_ptr_len(s); + + if (0 == len) { + tree_ptr = 0; + } else { + tree_ptr = RopeLeaf_from_char_ptr(alloc_copy(s, len), len); +# ifndef __GC + __stl_assert(1 == tree_ptr -> refcount); +# endif + } + } + + rope(const charT *s, size_t len) + { + if (0 == len) { + tree_ptr = 0; + } else { + tree_ptr = RopeLeaf_from_char_ptr(alloc_copy(s, len), len); + } + } + + rope(const charT *s, charT *e) + { + size_t len = e - s; + + if (0 == len) { + tree_ptr = 0; + } else { + tree_ptr = RopeLeaf_from_char_ptr(alloc_copy(s, len), len); + } + } + + rope(const const_iterator& s, const const_iterator& e) + { + tree_ptr = substring(s.root, s.current_pos, e.current_pos); + } + + rope(const iterator& s, const iterator& e) + { + tree_ptr = substring(s.root, s.current_pos, e.current_pos); + } + + rope(charT c) + { + charT * buf = (charT *)Alloc::allocate(rounded_up_size(1)); + + construct(buf, c); + tree_ptr = RopeLeaf_from_char_ptr(buf, 1); + } + + rope(size_t n, charT c); + + // Should really be templatized with respect to the iterator type + // and use sequence_buffer. (It should perhaps use sequence_buffer + // even now.) + rope(const charT *i, const charT *j) + { + if (i == j) { + tree_ptr = 0; + } else { + size_t len = j - i; + tree_ptr = RopeLeaf_from_char_ptr(alloc_copy(i, len), len); + } + } + + rope() + { + tree_ptr = 0; + } + + // Construct a rope from a function that can compute its members + rope(char_producer<charT> *fn, size_t len, bool delete_fn) + { + tree_ptr = RopeFunction_from_fn(fn, len, delete_fn); + } + + rope(const rope &x) + { + tree_ptr = x.tree_ptr; + ref(tree_ptr); + } + + ~rope() + { + unref(tree_ptr); + } + + rope& operator=(const rope& x) + { + RopeBase *old = tree_ptr; + tree_ptr = x.tree_ptr; + ref(tree_ptr); + unref(old); + return(*this); + } + + void push_back(charT x) + { + RopeBase *old = tree_ptr; + tree_ptr = concat_char_iter(tree_ptr, &x, 1); + unref(old); + } + + void pop_back() + { + RopeBase *old = tree_ptr; + tree_ptr = substring(tree_ptr, 0, tree_ptr -> size - 1); + unref(old); + } + + charT back() const + { + return fetch(tree_ptr, tree_ptr -> size - 1); + } + + void push_front(const charT& x) + { + RopeBase *old = tree_ptr; + charT *buf = alloc_copy(&x, 1); + RopeBase *left; + + __STL_TRY + left = RopeLeaf_from_char_ptr(buf, 1); + __STL_UNWIND(RopeBase::free_string(buf, 1)) + __STL_TRY + tree_ptr = concat(left, tree_ptr); + unref(old); + __STL_ALWAYS(unref(left)) + } + + void pop_front() + { + RopeBase *old = tree_ptr; + tree_ptr = substring(tree_ptr, 1, tree_ptr -> size); + unref(old); + } + + charT front() const + { + return fetch(tree_ptr, 0); + } + + void balance() + { + RopeBase *old = tree_ptr; + tree_ptr = balance(tree_ptr); + unref(old); + } + + void copy(charT * buffer) const { + destroy(buffer, buffer + size()); + flatten(tree_ptr, buffer); + } + + // This is the copy function from the standard, but + // with the arguments reordered to make it consistent with the + // rest of the interface. + // Note that this guaranteed not to compile if the draft standard + // order is assumed. + size_type copy(size_type pos, size_type n, charT *buffer) const { + size_t sz = size(); + size_t len = (pos + n > sz? sz - pos : n); + + destroy(buffer, buffer + len); + flatten(tree_ptr, pos, len, buffer); + return len; + } + + // Print to stdout, exposing structure. May be useful for + // performance debugging. + void dump() { + dump(tree_ptr); + } + + // Convert to 0 terminated string in new allocated memory. + // Embedded 0s in the input do not terminate the copy. + const charT * c_str() const; + + // As above, but lso use the flattened representation as the + // the new rope representation. + const charT * replace_with_c_str(); + + // Reclaim memory for the c_str generated flattened string. + // Intentionally undocumented, since it's hard to say when this + // is safe for multiple threads. + void delete_c_str () { + if (0 == tree_ptr) return; + if (RopeBase::leaf == tree_ptr -> tag + && ((RopeLeaf *)tree_ptr) -> data == tree_ptr -> c_string) { + // Representation shared + return; + } +# ifndef __GC + tree_ptr -> free_c_string(); +# endif + tree_ptr -> c_string = 0; + } + + charT operator[] (size_type pos) const { + return fetch(tree_ptr, pos); + } + + charT at(size_type pos) const { + // if (pos >= size()) throw out_of_range; + return (*this)[pos]; + } + + const_iterator begin() const { + return(const_iterator(tree_ptr, 0)); + } + + // An easy way to get a const iterator from a non-const container. + const_iterator const_begin() const { + return(const_iterator(tree_ptr, 0)); + } + + const_iterator end() const { + return(const_iterator(tree_ptr, size())); + } + + const_iterator const_end() const { + return(const_iterator(tree_ptr, size())); + } + + size_type size() const { + return(0 == tree_ptr? 0 : tree_ptr -> size); + } + + size_type length() const { + return size(); + } + + size_type max_size() const { + return min_len[RopeBase::max_rope_depth-1] - 1; + // Guarantees that the result can be sufficirntly + // balanced. Longer ropes will probably still work, + // but it's harder to make guarantees. + } + + typedef reverse_iterator<const_iterator, value_type, const_reference, + difference_type> const_reverse_iterator; + + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + + const_reverse_iterator const_rbegin() const { + return const_reverse_iterator(end()); + } + + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + + const_reverse_iterator const_rend() const { + return const_reverse_iterator(begin()); + } + + friend rope<charT,Alloc> operator+ (const rope<charT,Alloc> &left, + const rope<charT,Alloc> &right); + + friend rope<charT,Alloc> operator+ (const rope<charT,Alloc> &left, + const charT* right); + + friend rope<charT,Alloc> operator+ (const rope<charT,Alloc> &left, + charT right); + + // The symmetric cases are intentionally omitted, since they're presumed + // to be less common, and we don't handle them as well. + + // The following should really be templatized. + // The first argument should be an input iterator or + // forward iterator with value_type charT. + rope& append(const charT* iter, size_t n) { + RopeBase* result = destr_concat_char_iter(tree_ptr, iter, n); + unref(tree_ptr); + tree_ptr = result; + return *this; + } + + rope& append(const charT* c_string) { + size_t len = char_ptr_len(c_string); + append(c_string, len); + return(*this); + } + + rope& append(const charT* s, const charT* e) { + RopeBase* result = + destr_concat_char_iter(tree_ptr, s, e - s); + unref(tree_ptr); + tree_ptr = result; + return *this; + } + + rope& append(const_iterator s, const_iterator e) { + __stl_assert(s.root == e.root); + self_destruct_ptr appendee(substring(s.root, s.current_pos, + e.current_pos)); + RopeBase* result = concat(tree_ptr, (RopeBase *)appendee); + unref(tree_ptr); + tree_ptr = result; + return *this; + } + + rope& append(charT c) { + RopeBase* result = destr_concat_char_iter(tree_ptr, &c, 1); + unref(tree_ptr); + tree_ptr = result; + return *this; + } + + rope& append() { return append(charT()); } + + rope& append(const rope& y) { + RopeBase* result = concat(tree_ptr, y.tree_ptr); + unref(tree_ptr); + tree_ptr = result; + return *this; + } + + rope& append(size_t n, charT c) { + rope<charT,Alloc> last(n, c); + return append(last); + } + + void swap(rope& b) { + RopeBase * tmp = tree_ptr; + tree_ptr = b.tree_ptr; + b.tree_ptr = tmp; + } + + + protected: + // Result is included in refcount. + static RopeBase * replace(RopeBase *old, size_t pos1, + size_t pos2, RopeBase *r) { + if (0 == old) { ref(r); return r; } + self_destruct_ptr left(substring(old, 0, pos1)); + self_destruct_ptr right(substring(old, pos2, old -> size)); + RopeBase * result; + + if (0 == r) { + result = concat(left, right); + } else { + self_destruct_ptr left_result(concat(left, r)); + result = concat(left_result, right); + } + return result; + } + + public: + void insert(size_t p, const rope& r) { + RopeBase * result = replace(tree_ptr, p, p, + r.tree_ptr); + unref(tree_ptr); + tree_ptr = result; + } + + void insert(size_t p, size_t n, charT c) { + rope<charT,Alloc> r(n,c); + insert(p, r); + } + + void insert(size_t p, const charT * i, size_t n) { + self_destruct_ptr left(substring(tree_ptr, 0, p)); + self_destruct_ptr right(substring(tree_ptr, p, size())); + self_destruct_ptr left_result(concat_char_iter(left, i, n)); + RopeBase * result = + concat(left_result, right); + unref(tree_ptr); + tree_ptr = result; + } + + void insert(size_t p, const charT * c_string) { + insert(p, c_string, char_ptr_len(c_string)); + } + + void insert(size_t p, charT c) { + insert(p, &c, 1); + } + + void insert(size_t p) { + charT c = charT(); + insert(p, &c, 1); + } + + void insert(size_t p, const charT *i, const charT *j) { + rope r(i, j); + insert(p, r); + } + + void insert(size_t p, const const_iterator& i, + const const_iterator& j) { + rope r(i, j); + insert(p, r); + } + + void insert(size_t p, const iterator& i, + const iterator& j) { + rope r(i, j); + insert(p, r); + } + + // (position, length) versions of replace operations: + + void replace(size_t p, size_t n, const rope& r) { + RopeBase * result = replace(tree_ptr, p, p + n, + r.tree_ptr); + unref(tree_ptr); + tree_ptr = result; + } + + void replace(size_t p, size_t n, const charT *i, size_t i_len) { + rope r(i, i_len); + replace(p, n, r); + } + + void replace(size_t p, size_t n, charT c) { + rope r(c); + replace(p, n, r); + } + + void replace(size_t p, size_t n, const charT *c_string) { + rope r(c_string); + replace(p, n, r); + } + + void replace(size_t p, size_t n, const charT *i, const charT *j) { + rope r(i, j); + replace(p, n, r); + } + + void replace(size_t p, size_t n, + const const_iterator& i, const const_iterator& j) { + rope r(i, j); + replace(p, n, r); + } + + void replace(size_t p, size_t n, + const iterator& i, const iterator& j) { + rope r(i, j); + replace(p, n, r); + } + + // Single character variants: + void replace(size_t p, charT c) { + iterator i(this, p); + *i = c; + } + + void replace(size_t p, const rope& r) { + replace(p, 1, r); + } + + void replace(size_t p, const charT *i, size_t i_len) { + replace(p, 1, i, i_len); + } + + void replace(size_t p, const charT *c_string) { + replace(p, 1, c_string); + } + + void replace(size_t p, const charT *i, const charT *j) { + replace(p, 1, i, j); + } + + void replace(size_t p, const const_iterator& i, + const const_iterator& j) { + replace(p, 1, i, j); + } + + void replace(size_t p, const iterator& i, + const iterator& j) { + replace(p, 1, i, j); + } + + // Erase, (position, size) variant. + void erase(size_t p, size_t n) { + RopeBase * result = replace(tree_ptr, p, p + n, 0); + unref(tree_ptr); + tree_ptr = result; + } + + // Erase, single character + void erase(size_t p) { + erase(p, p + 1); + } + + // Insert, iterator variants. + iterator insert(const iterator& p, const rope& r) + { insert(p.index(), r); return p; } + iterator insert(const iterator& p, size_t n, charT c) + { insert(p.index(), n, c); return p; } + iterator insert(const iterator& p, charT c) + { insert(p.index(), c); return p; } + iterator insert(const iterator& p ) + { insert(p.index()); return p; } + iterator insert(const iterator& p, const charT *c_string) + { insert(p.index(), c_string); return p; } + iterator insert(const iterator& p, const charT *i, size_t n) + { insert(p.index(), i, n); return p; } + iterator insert(const iterator& p, const charT *i, const charT *j) + { insert(p.index(), i, j); return p; } + iterator insert(const iterator& p, + const const_iterator& i, const const_iterator& j) + { insert(p.index(), i, j); return p; } + iterator insert(const iterator& p, + const iterator& i, const iterator& j) + { insert(p.index(), i, j); return p; } + + // Replace, range variants. + void replace(const iterator& p, const iterator& q, + const rope& r) + { replace(p.index(), q.index() - p.index(), r); } + void replace(const iterator& p, const iterator& q, charT c) + { replace(p.index(), q.index() - p.index(), c); } + void replace(const iterator& p, const iterator& q, + const charT * c_string) + { replace(p.index(), q.index() - p.index(), c_string); } + void replace(const iterator& p, const iterator& q, + const charT *i, size_t n) + { replace(p.index(), q.index() - p.index(), i, n); } + void replace(const iterator& p, const iterator& q, + const charT *i, const charT *j) + { replace(p.index(), q.index() - p.index(), i, j); } + void replace(const iterator& p, const iterator& q, + const const_iterator& i, const const_iterator& j) + { replace(p.index(), q.index() - p.index(), i, j); } + void replace(const iterator& p, const iterator& q, + const iterator& i, const iterator& j) + { replace(p.index(), q.index() - p.index(), i, j); } + + // Replace, iterator variants. + void replace(const iterator& p, const rope& r) + { replace(p.index(), r); } + void replace(const iterator& p, charT c) + { replace(p.index(), c); } + void replace(const iterator& p, const charT * c_string) + { replace(p.index(), c_string); } + void replace(const iterator& p, const charT *i, size_t n) + { replace(p.index(), i, n); } + void replace(const iterator& p, const charT *i, const charT *j) + { replace(p.index(), i, j); } + void replace(const iterator& p, const_iterator i, const_iterator j) + { replace(p.index(), i, j); } + void replace(const iterator& p, iterator i, iterator j) + { replace(p.index(), i, j); } + + // Iterator and range variants of erase + void erase(const iterator &p, const iterator &q) + { erase(p.index(), q.index() - p.index()); } + void erase(const iterator &p) + { erase(p.index(), 1); } + + rope substr(size_t start, size_t len = 1) const { + return rope<charT,Alloc>( + substring(tree_ptr, start, start + len)); + } + + rope substr(iterator start, iterator end) const { + return rope<charT,Alloc>( + substring(tree_ptr, start.index(), end.index())); + } + + rope substr(iterator start) const { + size_t pos = start.index(); + return rope<charT,Alloc>( + substring(tree_ptr, pos, pos + 1)); + } + + rope substr(const_iterator start, const_iterator end) const { + // This might eventually take advantage of the cache in the + // iterator. + return rope<charT,Alloc> + (substring(tree_ptr, start.index(), end.index())); + } + + rope<charT,Alloc> substr(const_iterator start) { + size_t pos = start.index(); + return rope<charT,Alloc>(substring(tree_ptr, pos, pos + 1)); + } + + size_type find(charT c, size_type pos = 0) const; + size_type find(charT *s, size_type pos = 0) const { + const_iterator result = search(const_begin() + pos, const_end(), + s, s + char_ptr_len(s)); + return result.index(); + } + + iterator mutable_begin() { + return(iterator(this, 0)); + } + + iterator mutable_end() { + return(iterator(this, size())); + } + + typedef reverse_iterator<iterator, value_type, reference, + difference_type> reverse_iterator; + + reverse_iterator mutable_rbegin() { + return reverse_iterator(mutable_end()); + } + + reverse_iterator mutable_rend() { + return reverse_iterator(mutable_begin()); + } + + reference mutable_reference_at(size_type pos) { + return reference(this, pos); + } + +# ifdef __STD_STUFF + reference operator[] (size_type pos) { + return charT_ref_proxy(this, pos); + } + + reference at(size_type pos) { + // if (pos >= size()) throw out_of_range; + return (*this)[pos]; + } + + void resize(size_type n, charT c) {} + void resize(size_type n) {} + void reserve(size_type res_arg = 0) {} + size_type capacity() const { + return max_size(); + } + + // Stuff below this line is dangerous because it's error prone. + // I would really like to get rid of it. + // copy function with funny arg ordering. + size_type copy(charT *buffer, size_type n, size_type pos = 0) + const { + return copy(pos, n, buffer); + } + + iterator end() { return mutable_end(); } + + iterator begin() { return mutable_begin(); } + + reverse_iterator rend() { return mutable_rend(); } + + reverse_iterator rbegin() { return mutable_rbegin(); } + +# else + + const_iterator end() { return const_end(); } + + const_iterator begin() { return const_begin(); } + + const_reverse_iterator rend() { return const_rend(); } + + const_reverse_iterator rbegin() { return const_rbegin(); } + +# endif + +}; + +template <class charT, class Alloc> +inline bool operator== (const __rope_const_iterator<charT,Alloc> & x, + const __rope_const_iterator<charT,Alloc> & y) { + return (x.current_pos == y.current_pos && x.root == y.root); +} + +template <class charT, class Alloc> +inline bool operator< (const __rope_const_iterator<charT,Alloc> & x, + const __rope_const_iterator<charT,Alloc> & y) { + return (x.current_pos < y.current_pos); +} + +template <class charT, class Alloc> +inline ptrdiff_t operator-(const __rope_const_iterator<charT,Alloc> & x, + const __rope_const_iterator<charT,Alloc> & y) { + return x.current_pos - y.current_pos; +} + +template <class charT, class Alloc> +inline __rope_const_iterator<charT,Alloc> +operator-(const __rope_const_iterator<charT,Alloc> & x, + ptrdiff_t n) { + return __rope_const_iterator<charT,Alloc>(x.root, x.current_pos - n); +} + +template <class charT, class Alloc> +inline __rope_const_iterator<charT,Alloc> +operator+(const __rope_const_iterator<charT,Alloc> & x, + ptrdiff_t n) { + return __rope_const_iterator<charT,Alloc>(x.root, x.current_pos + n); +} + +template <class charT, class Alloc> +inline __rope_const_iterator<charT,Alloc> +operator+(ptrdiff_t n, + const __rope_const_iterator<charT,Alloc> & x) { + return __rope_const_iterator<charT,Alloc>(x.root, x.current_pos + n); +} + +template <class charT, class Alloc> +inline bool operator== (const __rope_iterator<charT,Alloc> & x, + const __rope_iterator<charT,Alloc> & y) { + return (x.current_pos == y.current_pos && x.root_rope == y.root_rope); +} + +template <class charT, class Alloc> +inline bool operator< (const __rope_iterator<charT,Alloc> & x, + const __rope_iterator<charT,Alloc> & y) { + return (x.current_pos < y.current_pos); +} + +template <class charT, class Alloc> +inline ptrdiff_t operator-(const __rope_iterator<charT,Alloc> & x, + const __rope_iterator<charT,Alloc> & y) { + return x.current_pos - y.current_pos; +} + +template <class charT, class Alloc> +inline __rope_iterator<charT,Alloc> +operator-(const __rope_iterator<charT,Alloc> & x, + ptrdiff_t n) { + return __rope_iterator<charT,Alloc>(x.root_rope, x.current_pos - n); +} + +template <class charT, class Alloc> +inline __rope_iterator<charT,Alloc> +operator+(const __rope_iterator<charT,Alloc> & x, + ptrdiff_t n) { + return __rope_iterator<charT,Alloc>(x.root_rope, x.current_pos + n); +} + +template <class charT, class Alloc> +inline __rope_iterator<charT,Alloc> +operator+(ptrdiff_t n, + const __rope_iterator<charT,Alloc> & x) { + return __rope_iterator<charT,Alloc>(x.root_rope, x.current_pos + n); +} + +template <class charT, class Alloc> +inline +rope<charT,Alloc> +operator+ (const rope<charT,Alloc> &left, + const rope<charT,Alloc> &right) +{ + return rope<charT,Alloc> + (rope<charT,Alloc>::concat(left.tree_ptr, right.tree_ptr)); + // Inlining this should make it possible to keep left and + // right in registers. +} + +template <class charT, class Alloc> +inline +rope<charT,Alloc>& +operator+= (rope<charT,Alloc> &left, + const rope<charT,Alloc> &right) +{ + left.append(right); + return left; +} + +template <class charT, class Alloc> +inline +rope<charT,Alloc> +operator+ (const rope<charT,Alloc> &left, + const charT* right) { + size_t rlen = rope<charT,Alloc>::char_ptr_len(right); + return rope<charT,Alloc> + (rope<charT,Alloc>::concat_char_iter(left.tree_ptr, right, rlen)); +} + +template <class charT, class Alloc> +inline +rope<charT,Alloc>& +operator+= (rope<charT,Alloc> &left, + const charT* right) { + left.append(right); + return left; +} + +template <class charT, class Alloc> +inline +rope<charT,Alloc> +operator+ (const rope<charT,Alloc> &left, charT right) { + return rope<charT,Alloc> + (rope<charT,Alloc>::concat_char_iter(left.tree_ptr, &right, 1)); +} + +template <class charT, class Alloc> +inline +rope<charT,Alloc>& +operator+= (rope<charT,Alloc> &left, charT right) { + left.append(right); + return left; +} + +template <class charT, class Alloc> +bool +operator< (const rope<charT,Alloc> &left, const rope<charT,Alloc> &right) { + return left.compare(right) < 0; +} + +template <class charT, class Alloc> +bool +operator== (const rope<charT,Alloc> &left, const rope<charT,Alloc> &right) { + return left.compare(right) == 0; +} + +template <class charT, class Alloc> +inline bool operator== (const __rope_charT_ptr_proxy<charT,Alloc> & x, + const __rope_charT_ptr_proxy<charT,Alloc> & y) { + return (x.pos == y.pos && x.root == y.root); +} + +template<class charT, class Alloc> +ostream& operator<< (ostream& o, const rope<charT, Alloc>& r); + +typedef rope<char, __ALLOC> crope; +typedef rope<wchar_t, __ALLOC> wrope; + +inline crope::reference __mutable_reference_at(crope& c, size_t i) +{ + return c.mutable_reference_at(i); +} + +inline wrope::reference __mutable_reference_at(wrope& c, size_t i) +{ + return c.mutable_reference_at(i); +} + +inline void swap(crope x, crope y) { x.swap(y); } +inline void swap(wrope x, wrope y) { x.swap(y); } + +// Hash functions should probably be revisited later: +struct hash<crope> +{ + size_t operator()(const crope& str) const + { + size_t sz = str.size(); + + if (0 == sz) return 0; + return 13*str[0] + 5*str[sz - 1] + sz; + } +}; + +struct hash<wrope> +{ + size_t operator()(const wrope& str) const + { + size_t sz = str.size(); + + if (0 == sz) return 0; + return 13*str[0] + 5*str[sz - 1] + sz; + } +}; + +# include <ropeimpl.h> +# endif /* _ROPE_H */ diff --git a/libstdc++/stl/ropeimpl.h b/libstdc++/stl/ropeimpl.h new file mode 100644 index 0000000..b90bc08 --- /dev/null +++ b/libstdc++/stl/ropeimpl.h @@ -0,0 +1,1510 @@ +/* + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#if defined(_MSC_VER) +# include <ostream> +#else +# include <iostream.h> +#endif + +// Set buf_start, buf_end, and buf_ptr appropriately, filling tmp_buf +// if necessary. Assumes path_end[leaf_index] and leaf_pos are correct. +// Results in a valid buf_ptr if the iterator can be legitimately +// dereferenced. +template <class charT, class Alloc> +void __rope_iterator_base<charT,Alloc>::setbuf +(__rope_iterator_base<charT,Alloc> &x) +{ + const RopeBase * leaf = x.path_end[x.leaf_index]; + size_t leaf_pos = x.leaf_pos; + size_t pos = x.current_pos; + + switch(leaf -> tag) { + case RopeBase::leaf: + x.buf_start = ((__rope_RopeLeaf<charT,Alloc> *)leaf) -> data; + x.buf_ptr = x.buf_start + (pos - leaf_pos); + x.buf_end = x.buf_start + leaf -> size; + break; + case RopeBase::function: + case RopeBase::substringfn: + { + size_t len = iterator_buf_len; + size_t buf_start_pos = leaf_pos; + size_t leaf_end = leaf_pos + leaf -> size; + char_producer<charT> *fn = + ((__rope_RopeFunction<charT,Alloc> *)leaf) -> fn; + + if (buf_start_pos + len <= pos) { + buf_start_pos = pos - len/4; + if (buf_start_pos + len > leaf_end) { + buf_start_pos = leaf_end - len; + } + } + if (buf_start_pos + len > leaf_end) { + len = leaf_end - buf_start_pos; + } + (*fn)(buf_start_pos - leaf_pos, len, x.tmp_buf); + x.buf_ptr = x.tmp_buf + (pos - buf_start_pos); + x.buf_start = x.tmp_buf; + x.buf_end = x.tmp_buf + len; + } + break; + default: + __stl_assert(0); + } +} + +// Set path and buffer inside a rope iterator. We assume that +// pos and root are already set. +template <class charT, class Alloc> +void __rope_iterator_base<charT,Alloc>::setcache +(__rope_iterator_base<charT,Alloc> &x) +{ + const RopeBase * path[RopeBase::max_rope_depth+1]; + const RopeBase * curr_rope; + int curr_depth = -1; /* index into path */ + size_t curr_start_pos = 0; + size_t pos = x.current_pos; + unsigned char dirns = 0; // Bit vector indicating right turns in the path + + __stl_assert(pos <= x.root -> size); + if (pos >= x.root -> size) { + x.buf_ptr = 0; + return; + } + curr_rope = x.root; + if (0 != curr_rope -> c_string) { + /* Treat the root as a leaf. */ + x.buf_start = curr_rope -> c_string; + x.buf_end = curr_rope -> c_string + curr_rope -> size; + x.buf_ptr = curr_rope -> c_string + pos; + x.path_end[0] = curr_rope; + x.leaf_index = 0; + x.leaf_pos = 0; + return; + } + for(;;) { + ++curr_depth; + __stl_assert(curr_depth <= RopeBase::max_rope_depth); + path[curr_depth] = curr_rope; + switch(curr_rope -> tag) { + case RopeBase::leaf: + case RopeBase::function: + case RopeBase::substringfn: + x.leaf_pos = curr_start_pos; + goto done; + case RopeBase::concat: + { + __rope_RopeConcatenation<charT,Alloc> *c = + (__rope_RopeConcatenation<charT,Alloc> *)curr_rope; + RopeBase * left = c -> left; + size_t left_len = left -> size; + + dirns <<= 1; + if (pos >= curr_start_pos + left_len) { + dirns |= 1; + curr_rope = c -> right; + curr_start_pos += left_len; + } else { + curr_rope = left; + } + } + break; + } + } + done: + // Copy last section of path into path_end. + { + int i = -1; + int j = curr_depth + 1 - path_cache_len; + + if (j < 0) j = 0; + while (j <= curr_depth) { + x.path_end[++i] = path[j++]; + } + x.leaf_index = i; + } + x.path_directions = dirns; + setbuf(x); +} + +// Specialized version of the above. Assumes that +// the path cache is valid for the previous position. +template <class charT, class Alloc> +void __rope_iterator_base<charT,Alloc>::setcache_for_incr +(__rope_iterator_base<charT,Alloc> &x) +{ + int current_index = x.leaf_index; + const RopeBase * current_node = x.path_end[current_index]; + size_t len = current_node -> size; + size_t node_start_pos = x.leaf_pos; + unsigned char dirns = x.path_directions; + __rope_RopeConcatenation<charT,Alloc> * c; + + __stl_assert(x.current_pos <= x.root -> size); + if (x.current_pos - node_start_pos < len) { + /* More stuff in this leaf, we just didn't cache it. */ + setbuf(x); + return; + } + __stl_assert(node_start_pos + len == x.current_pos); + // node_start_pos is starting position of last_node. + while (--current_index >= 0) { + if (!(dirns & 1) /* Path turned left */) break; + current_node = x.path_end[current_index]; + c = (__rope_RopeConcatenation<charT,Alloc> *)current_node; + // Otherwise we were in the right child. Thus we should pop + // the concatenation node. + node_start_pos -= c -> left -> size; + dirns >>= 1; + } + if (current_index < 0) { + // We underflowed the cache. Punt. + setcache(x); + return; + } + current_node = x.path_end[current_index]; + c = (__rope_RopeConcatenation<charT,Alloc> *)current_node; + // current_node is a concatenation node. We are positioned on the first + // character in its right child. + // node_start_pos is starting position of current_node. + node_start_pos += c -> left -> size; + current_node = c -> right; + x.path_end[++current_index] = current_node; + dirns |= 1; + while (RopeBase::concat == current_node -> tag) { + ++current_index; + if (path_cache_len == current_index) { + int i; + for (i = 0; i < path_cache_len-1; i++) { + x.path_end[i] = x.path_end[i+1]; + } + --current_index; + } + current_node = + ((__rope_RopeConcatenation<charT,Alloc> *)current_node) -> left; + x.path_end[current_index] = current_node; + dirns <<= 1; + // node_start_pos is unchanged. + } + x.leaf_index = current_index; + x.leaf_pos = node_start_pos; + x.path_directions = dirns; + setbuf(x); +} + +template <class charT, class Alloc> +void __rope_iterator_base<charT,Alloc>::incr(size_t n) { + current_pos += n; + if (0 != buf_ptr) { + size_t chars_left = buf_end - buf_ptr; + if (chars_left > n) { + buf_ptr += n; + } else if (chars_left == n) { + buf_ptr += n; + setcache_for_incr(*this); + } else { + buf_ptr = 0; + } + } +} + +template <class charT, class Alloc> +void __rope_iterator_base<charT,Alloc>::decr(size_t n) { + if (0 != buf_ptr) { + size_t chars_left = buf_ptr - buf_start; + if (chars_left >= n) { + buf_ptr -= n; + } else { + buf_ptr = 0; + } + } + current_pos -= n; +} + +template <class charT, class Alloc> +void __rope_iterator<charT,Alloc>::check() { + if (root_rope -> tree_ptr != root) { + // Rope was modified. Get things fixed up. + RopeBase::unref(root); + root = root_rope -> tree_ptr; + RopeBase::ref(root); + buf_ptr = 0; + } +} + +template <class charT, class Alloc> +inline __rope_const_iterator<charT, Alloc>::__rope_const_iterator +(const __rope_iterator<charT,Alloc> & x) +: __rope_iterator_base<charT,Alloc>(x) { } + +template <class charT, class Alloc> +inline __rope_iterator<charT,Alloc>::__rope_iterator +(rope<charT,Alloc>& r, size_t pos) + : __rope_iterator_base<charT,Alloc>(r.tree_ptr, pos), root_rope(&r) { + RopeBase::ref(root); +} + +template <class charT, class Alloc> +inline size_t rope<charT,Alloc>::char_ptr_len(const charT *s) +{ + const charT *p = s; + + while (!is0(*p)) { ++p; } + return(p - s); +} + +template <class charT, class Alloc> +rope<charT,Alloc>::RopeLeaf * +rope<charT,Alloc>::RopeLeaf_from_char_ptr(__GC_CONST charT *s, size_t size) +{ + RopeLeaf *t = LAlloc::allocate(); + + t -> tag = RopeBase::leaf; + if (__is_basic_char_type((charT *)0)) { + // already eos terminated. + t -> c_string = s; + } else { + t -> c_string = 0; + } + t -> is_balanced = true; + t -> depth = 0; + t -> size = size; + t -> data = s; +# ifndef __GC + t -> refcount = 1; + t -> init_refcount_lock(); +# endif + return (t); +} + +# ifdef __GC +template <class charT, class Alloc> +void __rope_RopeBase<charT,Alloc>::fn_finalization_proc(void * tree, void *) +{ + delete ((__rope_RopeFunction<charT,Alloc> *)tree) -> fn; +} +# endif + +template <class charT, class Alloc> +rope<charT,Alloc>::RopeFunction * +rope<charT,Alloc>::RopeFunction_from_fn +(char_producer<charT> *fn, size_t size, bool delete_fn) +{ + if (0 == size) return 0; + RopeFunction *t = FAlloc::allocate(); + t -> tag = RopeBase::function; + t -> c_string = 0; + t -> is_balanced = true; + t -> depth = 0; + t -> size = size; + t -> fn = fn; +# ifdef __GC + if (delete_fn) { + GC_REGISTER_FINALIZER(t, RopeBase::fn_finalization_proc, 0, 0, 0); + } +# else + t -> delete_when_done = delete_fn; + t -> refcount = 1; + t -> init_refcount_lock(); +# endif + return (t); +} + +#ifndef __GC + +template <class charT, class Alloc> +inline void __rope_RopeBase<charT,Alloc>::free_c_string() +{ + charT * cstr = c_string; + if (0 != cstr) { + size_t sz = size + 1; + destroy(cstr, cstr + sz); + Alloc::deallocate(cstr, sz); + } +} + +template <class charT, class Alloc> +inline void __rope_RopeBase<charT,Alloc>::free_string(charT* s, size_t n) +{ + if (!__is_basic_char_type((charT *)0)) { + destroy(s, s + n); + } + Alloc::deallocate(s, rounded_up_size(n)); +} + +template <class charT, class Alloc> +void __rope_RopeBase<charT,Alloc>::free_tree() +{ + switch(tag) { + case leaf: + { + __rope_RopeLeaf<charT,Alloc> * l = + (__rope_RopeLeaf<charT,Alloc> *)this; + charT * d = l -> data; + + if (d != c_string) { + free_c_string(); + } + free_string(d, size); + LAlloc::deallocate(l); + } + break; + case concat: + { + __rope_RopeConcatenation<charT,Alloc> * c = + (__rope_RopeConcatenation<charT,Alloc> *)this; + __rope_RopeBase * left = c -> left; + __rope_RopeBase * right = c -> right; + free_c_string(); + left -> unref_nonnil(); + right -> unref_nonnil(); + CAlloc::deallocate(c); + } + break; + case function: + { + __rope_RopeFunction<charT,Alloc> * fn = + (__rope_RopeFunction<charT,Alloc> *)this; + free_c_string(); + if ( fn -> delete_when_done) { + delete fn -> fn; + } + FAlloc::deallocate(fn); + break; + } + case substringfn: + { + __rope_RopeSubstring<charT,Alloc> * ss = + (__rope_RopeSubstring<charT,Alloc> *)this; + __rope_RopeBase *base = ss -> base; + free_c_string(); + base -> unref_nonnil(); + SAlloc::deallocate(ss); + break; + } + } +} +#else + +template <class charT, class Alloc> +inline void __rope_RopeBase<charT,Alloc>::free_string(charT* s, size_t n) +{} + +#endif + + +// Concatenate a C string onto a leaf rope by copying the rope data. +// Used for short ropes. +template <class charT, class Alloc> +rope<charT,Alloc>::RopeLeaf * +rope<charT,Alloc>::leaf_concat_char_iter + (RopeLeaf * r, const charT * iter, size_t len) +{ + size_t old_len = r -> size; + charT * new_data = (charT *) + Alloc::allocate(rounded_up_size(old_len + len)); + RopeLeaf * result; + + uninitialized_copy_n(r -> data, old_len, new_data); + uninitialized_copy_n(iter, len, new_data + old_len); + __cond_store_eos(new_data[old_len + len]); + __STL_TRY + result = RopeLeaf_from_char_ptr(new_data, old_len + len); + __STL_UNWIND(RopeBase::free_string(new_data, old_len + len)); + return result; +} + +#ifndef __GC +// As above, but it's OK to clobber original if refcount is 1 +template <class charT, class Alloc> +rope<charT,Alloc>::RopeLeaf * +rope<charT,Alloc>::destr_leaf_concat_char_iter + (RopeLeaf * r, const charT * iter, size_t len) +{ + __stl_assert(r -> refcount >= 1); + if (r -> refcount > 1) return leaf_concat_char_iter(r, iter, len); + size_t old_len = r -> size; + if (allocated_capacity(old_len) >= old_len + len) { + // The space has been partially initialized for the standard + // character types. But that doesn't matter for those types. + uninitialized_copy_n(iter, len, r -> data + old_len); + if (__is_basic_char_type((charT *)0)) { + __cond_store_eos(r -> data[old_len + len]); + __stl_assert(r -> c_string == r -> data); + } else if (r -> c_string != r -> data && 0 != r -> c_string) { + r -> free_c_string(); + r -> c_string = 0; + } + r -> size = old_len + len; + __stl_assert(r -> refcount == 1); + r -> refcount = 2; + return r; + } else { + RopeLeaf * result = leaf_concat_char_iter(r, iter, len); + __stl_assert(result -> refcount == 1); + return result; + } +} +#endif + +// Assumes left and right are not 0. +// Result has ref count 1. +template <class charT, class Alloc> +rope<charT,Alloc>::RopeBase * +rope<charT,Alloc>::tree_concat (RopeBase * left, RopeBase * right) +{ + RopeConcatenation * result = CAlloc::allocate(); + unsigned char child_depth = left -> depth; + size_t rsize; + + result -> tag = RopeBase::concat; + result -> c_string = 0; + result -> is_balanced = false; + result -> size = rsize = left -> size + right -> size; + if (right -> depth > child_depth) child_depth = right -> depth; + unsigned char depth = child_depth + 1; + result -> depth = depth; + result -> left = left; + result -> right = right; +# ifndef __GC + result -> refcount = 1; + result -> init_refcount_lock(); +# endif + if (depth > 20 && (rsize < 1000 || depth > RopeBase::max_rope_depth)) { + RopeBase * balanced; + + __STL_TRY + balanced = balance(result); +# ifndef __GC + if (result != balanced) { + __stl_assert(1 == result -> refcount + && 1 == balanced -> refcount); + } +# endif + __STL_ALWAYS(result -> unref_nonnil()); + return balanced; + } else { + return result; + } +} + +template <class charT, class Alloc> +rope<charT,Alloc>::RopeBase * rope<charT,Alloc>::concat_char_iter + (RopeBase * r, const charT *s, size_t slen) +{ + RopeBase *result; + if (0 == slen) { + ref(r); + return r; + } + if (0 == r) return RopeLeaf_from_char_ptr(alloc_copy(s, slen), slen); + if (RopeBase::leaf == r -> tag && r -> size + slen <= copy_max) { + result = leaf_concat_char_iter((RopeLeaf *)r, s, slen); +# ifndef __GC + __stl_assert(1 == result -> refcount); +# endif + return result; + } + if (RopeBase::concat == r -> tag + && RopeBase::leaf == ((RopeConcatenation *)r) -> right -> tag) { + RopeLeaf *right = (RopeLeaf *)(((RopeConcatenation *)r) -> right); + if (right -> size + slen <= copy_max) { + RopeBase * left = ((RopeConcatenation *)r) -> left; + left -> ref_nonnil(); + __STL_TRY + result = tree_concat(left, + leaf_concat_char_iter((RopeLeaf *)right, + s, slen)); + __STL_UNWIND(unref(left)); +# ifndef __GC + __stl_assert(1 == result -> refcount); +# endif + return result; + } + } + __STL_TRY + r -> ref_nonnil(); + result = tree_concat(r, RopeLeaf_from_char_ptr(alloc_copy(s, slen), + slen)); + __STL_UNWIND(unref(r)); +# ifndef __GC + __stl_assert(1 == result -> refcount); +# endif + return result; +} + +#ifndef __GC +template <class charT, class Alloc> +rope<charT,Alloc>::RopeBase * rope<charT,Alloc> +::destr_concat_char_iter + (RopeBase * r, const charT *s, size_t slen) +{ + RopeBase *result; + if (0 == r) return RopeLeaf_from_char_ptr(alloc_copy(s, slen), slen); + size_t count = r -> refcount; + size_t orig_size = r -> size; + __stl_assert(count >= 1); + if (count > 1) return concat_char_iter(r, s, slen); + if (0 == slen) { + r -> refcount = 2; // One more than before + return r; + } + if (orig_size + slen <= copy_max && RopeBase::leaf == r -> tag) { + result = destr_leaf_concat_char_iter((RopeLeaf *)r, s, slen); + return result; + } + if (RopeBase::concat == r -> tag) { + RopeLeaf *right = (RopeLeaf *)(((RopeConcatenation *)r) -> right); + if (RopeBase::leaf == right -> tag + && right -> size + slen <= copy_max) { + RopeBase * new_right = destr_leaf_concat_char_iter(right, s, slen); + if (right == new_right) { + __stl_assert(new_right -> refcount == 2); + new_right -> refcount = 1; + } else { + __stl_assert(new_right -> refcount >= 1); + right -> unref_nonnil(); + } + __stl_assert(r -> refcount == 1); + r -> refcount = 2; // One more than before. + ((RopeConcatenation *)r) -> right = new_right; + r -> size = orig_size + slen; + if (0 != r -> c_string) { + r -> free_c_string(); + r -> c_string = 0; + } + return r; + } + } + charT * cpy = alloc_copy(s, slen); + r -> ref_nonnil(); + __STL_TRY + result = tree_concat(r, RopeLeaf_from_char_ptr(cpy, slen)); + __STL_UNWIND(unref(r); RopeBase::free_string(cpy,slen)) + __stl_assert(1 == result -> refcount); + return result; +} +#endif /* !__GC */ + +template <class charT, class Alloc> +rope<charT,Alloc>::RopeBase * +rope<charT,Alloc>::concat(RopeBase * left, RopeBase * right) +{ + if (0 == left) { + ref(right); + return right; + } + if (0 == right) { + left -> ref_nonnil(); + return left; + } + if (RopeBase::leaf == right -> tag) { + if (RopeBase::leaf == left -> tag) { + if (right -> size + left -> size <= copy_max) { + return leaf_concat_char_iter((RopeLeaf *)left, + ((RopeLeaf *)right) -> data, + right -> size); + } + } else if (RopeBase::concat == left -> tag + && RopeBase::leaf == + ((RopeConcatenation *)left) -> right -> tag) { + RopeLeaf * leftright = + (RopeLeaf *)(((RopeConcatenation *)left) -> right); + if (leftright -> size + right -> size <= copy_max) { + RopeBase * leftleft = ((RopeConcatenation *)left) -> left; + RopeBase * rest = leaf_concat_char_iter(leftright, + ((RopeLeaf *)right) -> data, + right -> size); + leftleft -> ref_nonnil(); + __STL_TRY + return(tree_concat(leftleft, rest)); + __STL_UNWIND(unref(left); unref(rest)) + } + } + } + left -> ref_nonnil(); + right -> ref_nonnil(); + return(tree_concat(left, right)); +} + +template <class charT, class Alloc> +rope<charT,Alloc>::RopeBase * +rope<charT,Alloc>::substring(RopeBase * base, size_t start, size_t endp1) +{ + if (0 == base) return 0; + size_t len = base -> size; + size_t adj_endp1; + const size_t lazy_threshold = 128; + + if (endp1 >= len) { + if (0 == start) { + base -> ref_nonnil(); + return base; + } else { + adj_endp1 = len; + } + } else { + adj_endp1 = endp1; + } + switch(base -> tag) { + case RopeBase::concat: + { + RopeConcatenation *c = (RopeConcatenation *)base; + RopeBase *left = c -> left; + RopeBase *right = c -> right; + size_t left_len = left -> size; + RopeBase * result; + + if (adj_endp1 <= left_len) { + return substring(left, start, endp1); + } else if (start >= left_len) { + return substring(right, start - left_len, + adj_endp1 - left_len); + } + self_destruct_ptr left_result(substring(left, start, + left_len)); + self_destruct_ptr right_result( + substring(right, 0, endp1 - left_len)); + result = concat(left_result, right_result); +# ifndef __GC + __stl_assert(1 == result -> refcount); +# endif + return result; + } + case RopeBase::leaf: + { + RopeLeaf * l = (RopeLeaf *)base; + RopeLeaf * result; + __GC_CONST charT *section; + size_t result_len; + if (start >= adj_endp1) return 0; + result_len = adj_endp1 - start; + if (result_len > lazy_threshold) goto lazy; +# ifdef __GC + section = l -> data + start; + result = RopeLeaf_from_char_ptr(section, result_len); + result -> c_string = 0; // Not eos terminated. +# else + section = alloc_copy(l -> data + start, result_len); + // We should sometimes create substring node instead. + __STL_TRY + result = RopeLeaf_from_char_ptr(section, result_len); + __STL_UNWIND(RopeBase::free_string(section, result_len)) +# endif + return result; + } + case RopeBase::substringfn: + // Avoid introducing mutiple layers of substring nodes. + { + RopeSubstring *old = (RopeSubstring *)base; + size_t result_len; + if (start >= adj_endp1) return 0; + result_len = adj_endp1 - start; + if (result_len > lazy_threshold) { + RopeSubstring * space = SAlloc::allocate(); + RopeSubstring * result = + new(space) RopeSubstring(old -> base, + start + old -> start, + adj_endp1 - start); + return result; + } // else fall through: + } + case RopeBase::function: + { + RopeFunction * f = (RopeFunction *)base; + charT *section; + size_t result_len; + if (start >= adj_endp1) return 0; + result_len = adj_endp1 - start; + + if (result_len > lazy_threshold) goto lazy; + section = (charT *) + Alloc::allocate(rounded_up_size(result_len)); + __STL_TRY + (*(f -> fn))(start, result_len, section); + __STL_UNWIND(RopeBase::free_string(section, result_len)); + __cond_store_eos(section[result_len]); + return RopeLeaf_from_char_ptr(section, result_len); + } + } + /*NOTREACHED*/ + __stl_assert(false); + lazy: + { + // Create substring node. + RopeSubstring * space = SAlloc::allocate(); + RopeSubstring * result = new(space) RopeSubstring(base, start, + adj_endp1 - start); + return result; + } +} + +template<class charT> +class __rope_flatten_char_consumer : public __rope_char_consumer<charT> { + private: + charT * buf_ptr; + public: + charT * buffer; + __rope_flatten_char_consumer(charT * buffer) { + buf_ptr = buffer; + }; + ~__rope_flatten_char_consumer() {} + bool operator() (const charT* leaf, size_t n) { + uninitialized_copy_n(leaf, n, buf_ptr); + buf_ptr += n; + return true; + } +}; + +template<class charT> +class __rope_find_char_char_consumer : public __rope_char_consumer<charT> { + private: + charT pattern; + public: + size_t count; // Number of nonmatching characters + __rope_find_char_char_consumer(charT p) : pattern(p), count(0) {} + ~__rope_find_char_char_consumer() {} + bool operator() (const charT* leaf, size_t n) { + size_t i; + for (i = 0; i < n; i++) { + if (leaf[i] == pattern) { + count += i; return false; + } + } + count += n; return true; + } +}; + +template<class charT> +class __rope_insert_char_consumer : public __rope_char_consumer<charT> { + private: + typedef ostream insert_ostream; + insert_ostream & o; + public: + charT * buffer; + __rope_insert_char_consumer(insert_ostream & writer) : o(writer) {}; + ~__rope_insert_char_consumer() { }; + // Caller is presumed to own the ostream + bool operator() (const charT* leaf, size_t n); + // Returns true to continue traversal. +}; + +template<class charT> +bool __rope_insert_char_consumer<charT>::operator() + (const charT * leaf, size_t n) +{ + size_t i; + // We assume that formatting is set up correctly for each element. + for (i = 0; i < n; i++) o << leaf[i]; + return true; +} + +inline bool __rope_insert_char_consumer<char>::operator() + (const char * leaf, size_t n) +{ + size_t i; + for (i = 0; i < n; i++) o.put(leaf[i]); + return true; +} + +#if !defined(_MSC_VER) && !defined(__BORLANDC__) +// I couldn't get this to work work with the VC++ version of basic_ostream. +inline bool __rope_insert_char_consumer<wchar_t>::operator() + (const wchar_t * leaf, size_t n) +{ + size_t i; + for (i = 0; i < n; i++) o.put(leaf[i]); + return true; +} +#endif /* !_MSC_VER && !BORLAND */ + +template <class charT, class Alloc> +bool rope<charT, Alloc>::apply_to_pieces( + __rope_char_consumer<charT>& c, + const RopeBase * r, + size_t begin, size_t end) +{ + if (0 == r) return true; + switch(r -> tag) { + case RopeBase::concat: + { + RopeConcatenation *conc = (RopeConcatenation *)r; + RopeBase *left = conc -> left; + size_t left_len = left -> size; + if (begin < left_len) { + size_t left_end = min(left_len, end); + if (!apply_to_pieces(c, left, begin, left_end)) { + return false; + } + } + if (end > left_len) { + RopeBase *right = conc -> right; + size_t right_start = max(left_len, begin); + if (!apply_to_pieces(c, right, + right_start - left_len, + end - left_len)) { + return false; + } + } + } + return true; + case RopeBase::leaf: + { + RopeLeaf * l = (RopeLeaf *)r; + return c(l -> data + begin, end - begin); + } + case RopeBase::function: + case RopeBase::substringfn: + { + RopeFunction * f = (RopeFunction *)r; + size_t len = end - begin; + bool result; + charT * buffer = (charT *) + Alloc::allocate(len * sizeof(charT)); + __STL_TRY + (*(f -> fn))(begin, end, buffer); + result = c(buffer, len); + __STL_ALWAYS(Alloc::deallocate(buffer, len * sizeof(charT))) + return result; + } + default: + __stl_assert(false); + /*NOTREACHED*/ + return false; + } +} + +inline void __rope_fill(ostream& o, size_t n) +{ + char f = cout.fill(); + size_t i; + + for (i = 0; i < n; i++) o.put(f); +} + + +template <class charT> inline bool __rope_is_simple(charT *c) { return false; } +inline bool __rope_is_simple(char * c) { return true; } +inline bool __rope_is_simple(wchar_t * c) { return true; } + + +template<class charT, class Alloc> +ostream& operator<< (ostream& o, const rope<charT, Alloc>& r) +{ + size_t w = o.width(); + bool left = o.flags() & ios::left; + size_t pad_len; + size_t rope_len = r.size(); + __rope_insert_char_consumer<charT> c(o); + bool is_simple = __rope_is_simple((charT *)0); + + if (rope_len < w) { + pad_len = w - rope_len; + } else { + pad_len = 0; + } + if (!is_simple) o.width(w/rope_len); + __STL_TRY + if (is_simple && !left && pad_len > 0) { + __rope_fill(o, pad_len); + } + r.apply_to_pieces(0, r.size(), c); + if (is_simple && left && pad_len > 0) { + __rope_fill(o, pad_len); + } + __STL_ALWAYS(if (!is_simple) o.width(w)) + return o; +} + +template <class charT, class Alloc> +charT * +rope<charT,Alloc>::flatten(RopeBase * r, + size_t start, size_t len, + charT * buffer) +{ + __rope_flatten_char_consumer<charT> c(buffer); + apply_to_pieces(c, r, start, start + len); + return(buffer + len); +} + +template <class charT, class Alloc> +size_t +rope<charT,Alloc>::find(charT pattern, size_t start) const +{ + __rope_find_char_char_consumer<charT> c(pattern); + apply_to_pieces(c, tree_ptr, start, size()); + return start + c.count; +} + +template <class charT, class Alloc> +charT * +rope<charT,Alloc>::flatten(RopeBase * r, charT * buffer) +{ + if (0 == r) return buffer; + switch(r -> tag) { + case RopeBase::concat: + { + RopeConcatenation *c = (RopeConcatenation *)r; + RopeBase *left = c -> left; + RopeBase *right = c -> right; + charT * rest = flatten(left, buffer); + return flatten(right, rest); + } + case RopeBase::leaf: + { + RopeLeaf * l = (RopeLeaf *)r; + return copy_n(l -> data, l -> size, buffer); + } + case RopeBase::function: + case RopeBase::substringfn: + // We dont yet do anything with substring nodes. + // This needs to be fixed before ropefiles will work well. + { + RopeFunction * f = (RopeFunction *)r; + (*(f -> fn))(0, f -> size, buffer); + return buffer + f -> size; + } + default: + __stl_assert(false); + /*NOTREACHED*/ + return 0; + } +} + + +// This needs work for charT != char +template <class charT, class Alloc> +void +rope<charT,Alloc>::dump(RopeBase * r, int indent) +{ + for (int i = 0; i < indent; i++) putchar(' '); + if (0 == r) { + printf("NULL\n"); return; + } + if (RopeBase::concat == r -> tag) { + RopeConcatenation *c = (RopeConcatenation *)r; + RopeBase *left = c -> left; + RopeBase *right = c -> right; + +# ifdef __GC + printf("Concatenation %p (depth = %d, len = %ld, %s balanced)\n", + r, r -> depth, r -> size, r -> is_balanced? "" : "not"); +# else + printf("Concatenation %p (rc = %ld, depth = %d, len = %ld, %s balanced)\n", + r, r -> refcount, r -> depth, r -> size, + r -> is_balanced? "" : "not"); +# endif + dump(left, indent + 2); + dump(right, indent + 2); + return; + } else { + char * kind; + + switch (r -> tag) { + case RopeBase::leaf: + kind = "Leaf"; + break; + case RopeBase::function: + kind = "Function"; + break; + case RopeBase::substringfn: + kind = "Function representing substring"; + break; + default: + kind = "(corrupted kind field!)"; + } +# ifdef __GC + printf("%s %p (depth = %d, len = %ld) ", + kind, r, r -> depth, r -> size); +# else + printf("%s %p (rc = %ld, depth = %d, len = %ld) ", + kind, r, r -> refcount, r -> depth, r -> size); +# endif + if (__is_one_byte_char_type((charT *)0)) { + const int max_len = 40; + self_destruct_ptr prefix(substring(r, 0, max_len)); + charT buffer[max_len + 1]; + bool too_big = r -> size > prefix-> size; + + flatten(prefix, buffer); + buffer[prefix -> size] = __eos((charT *)0); + printf("%s%s\n", (char *)buffer, too_big? "...\n" : "\n"); + } else { + printf("\n"); + } + } +} + +template <class charT, class Alloc> +const unsigned long +rope<charT,Alloc>::min_len[__rope_RopeBase<charT,Alloc>::max_rope_depth + 1] = { +/* 0 */1, /* 1 */2, /* 2 */3, /* 3 */5, /* 4 */8, /* 5 */13, /* 6 */21, +/* 7 */34, /* 8 */55, /* 9 */89, /* 10 */144, /* 11 */233, /* 12 */377, +/* 13 */610, /* 14 */987, /* 15 */1597, /* 16 */2584, /* 17 */4181, +/* 18 */6765, /* 19 */10946, /* 20 */17711, /* 21 */28657, /* 22 */46368, +/* 23 */75025, /* 24 */121393, /* 25 */196418, /* 26 */317811, +/* 27 */514229, /* 28 */832040, /* 29 */1346269, /* 30 */2178309, +/* 31 */3524578, /* 32 */5702887, /* 33 */9227465, /* 34 */14930352, +/* 35 */24157817, /* 36 */39088169, /* 37 */63245986, /* 38 */102334155, +/* 39 */165580141, /* 40 */267914296, /* 41 */433494437, +/* 42 */701408733, /* 43 */1134903170, /* 44 */1836311903, +/* 45 */2971215073 }; +// These are Fibonacci numbers < 2**32. + +template <class charT, class Alloc> +rope<charT,Alloc>::RopeBase * +rope<charT,Alloc>::balance(RopeBase *r) +{ + RopeBase * forest[RopeBase::max_rope_depth + 1]; + RopeBase * result = 0; + int i; + // Inariant: + // The concatenation of forest in descending order is equal to r. + // forest[i].size >= min_len[i] + // forest[i].depth = i + // References from forest are included in refcount. + + for (i = 0; i <= RopeBase::max_rope_depth; ++i) forest[i] = 0; + __STL_TRY + add_to_forest(r, forest); + for (i = 0; i <= RopeBase::max_rope_depth; ++i) if (0 != forest[i]) { +# ifndef __GC + self_destruct_ptr old(result); +# endif + result = concat(forest[i], result); + forest[i] -> unref_nonnil(); + } + __STL_UNWIND(for(i = 0; i <= RopeBase::max_rope_depth; i++) + unref(forest[i])) + if (result -> depth > RopeBase::max_rope_depth) abort(); + return(result); +} + + +template <class charT, class Alloc> +void +rope<charT,Alloc>::add_to_forest(RopeBase *r, RopeBase **forest) +{ + if (r -> is_balanced) { + add_leaf_to_forest(r, forest); + return; + } + __stl_assert(r -> tag == RopeBase::concat); + { + RopeConcatenation *c = (RopeConcatenation *)r; + + add_to_forest(c -> left, forest); + add_to_forest(c -> right, forest); + } +} + + +template <class charT, class Alloc> +void +rope<charT,Alloc>::add_leaf_to_forest(RopeBase *r, RopeBase **forest) +{ + self_destruct_ptr insertee(r); // included in refcount + self_destruct_ptr too_tiny(0); // included in refcount + int i; // forest[0..i-1] is empty + size_t s = insertee -> size; + + ref(r); + for (i = 0; s >= min_len[i+1]/* not this bucket */; ++i) { + if (0 != forest[i]) { +# ifndef __GC + self_destruct_ptr old(too_tiny); +# endif + too_tiny = concat_and_set_balanced(forest[i], too_tiny); + forest[i] -> unref_nonnil(); + forest[i] = 0; + } + } + { +# ifndef __GC + self_destruct_ptr old(insertee); +# endif + insertee = concat_and_set_balanced(too_tiny, insertee); + } + unref(too_tiny); // too_tiny is dead. + too_tiny = 0; // Needed for exception safety. + __stl_assert(is_almost_balanced(insertee)); + __stl_assert(insertee -> depth <= r -> depth + 1); + for (;; ++i) { + if (0 != forest[i]) { +# ifndef __GC + self_destruct_ptr old(insertee); +# endif + insertee = concat_and_set_balanced(forest[i], insertee); + forest[i] -> unref_nonnil(); + forest[i] = 0; + __stl_assert(is_almost_balanced(insertee)); + } + __stl_assert(min_len[i] <= insertee -> size); + __stl_assert(forest[i] == 0); + if (i == RopeBase::max_rope_depth + || insertee -> size < min_len[i+1]) { + forest[i] = insertee; + insertee = 0; + // refcount is OK since insertee is now dead. + return; + } + } +} + +template <class charT, class Alloc> +charT +rope<charT,Alloc>::fetch(RopeBase *r, size_type i) +{ + __GC_CONST charT * cstr = r -> c_string; + + __stl_assert(i < r -> size); + if (0 != cstr) return cstr[i]; + for(;;) { + switch(r -> tag) { + case RopeBase::concat: + { + RopeConcatenation *c = (RopeConcatenation *)r; + RopeBase *left = c -> left; + size_t left_len = left -> size; + + if (i >= left_len) { + i -= left_len; + r = c -> right; + } else { + r = left; + } + } + break; + case RopeBase::leaf: + { + RopeLeaf * l = (RopeLeaf *)r; + return l -> data[i]; + } + case RopeBase::function: + case RopeBase::substringfn: + { + RopeFunction * f = (RopeFunction *)r; + charT result; + + (*(f -> fn))(i, 1, &result); + return result; + } + } + } +} + +# ifndef __GC +// Return a uniquely referenced character slot for the given +// position, or 0 if that's not possible. +template <class charT, class Alloc> +charT* +rope<charT,Alloc>::fetch_ptr(RopeBase *r, size_type i) +{ + RopeBase * clrstack[RopeBase::max_rope_depth]; + size_t csptr = 0; + + for(;;) { + if (r -> refcount > 1) return 0; + switch(r -> tag) { + case RopeBase::concat: + { + RopeConcatenation *c = (RopeConcatenation *)r; + RopeBase *left = c -> left; + size_t left_len = left -> size; + + if (c -> c_string != 0) clrstack[csptr++] = c; + if (i >= left_len) { + i -= left_len; + r = c -> right; + } else { + r = left; + } + } + break; + case RopeBase::leaf: + { + RopeLeaf * l = (RopeLeaf *)r; + if (l -> c_string != l -> data && l -> c_string != 0) + clrstack[csptr++] = l; + while (csptr > 0) { + -- csptr; + RopeBase * d = clrstack[csptr]; + d -> free_c_string(); + d -> c_string = 0; + } + return l -> data + i; + } + case RopeBase::function: + case RopeBase::substringfn: + return 0; + } + } +} +# endif /* __GC */ + +// The following could be implemented trivially using +// lexicographical_compare_3way. +// We do a little more work to avoid dealing with rope iterators for +// flat strings. +template <class charT, class Alloc> +int +rope<charT,Alloc>::compare (const RopeBase *left, const RopeBase *right) +{ + size_t left_len; + size_t right_len; + + if (0 == right) return 0 != left; + if (0 == left) return -1; + left_len = left -> size; + right_len = right -> size; + if (RopeBase::leaf == left -> tag) { + RopeLeaf *l = (RopeLeaf *) left; + if (RopeBase::leaf == right -> tag) { + RopeLeaf *r = (RopeLeaf *) right; + return lexicographical_compare_3way( + l -> data, l -> data + left_len, + r -> data, r -> data + right_len); + } else { + const_iterator rstart(right, 0); + const_iterator rend(right, right_len); + return lexicographical_compare_3way( + l -> data, l -> data + left_len, + rstart, rend); + } + } else { + const_iterator lstart(left, 0); + const_iterator lend(left, left_len); + if (RopeBase::leaf == right -> tag) { + RopeLeaf *r = (RopeLeaf *) right; + return lexicographical_compare_3way( + lstart, lend, + r -> data, r -> data + right_len); + } else { + const_iterator rstart(right, 0); + const_iterator rend(right, right_len); + return lexicographical_compare_3way( + lstart, lend, + rstart, rend); + } + } +} + +// Assignment to reference proxies. +template <class charT, class Alloc> +__rope_charT_ref_proxy<charT, Alloc>& +__rope_charT_ref_proxy<charT, Alloc>::operator= (charT c) { + RopeBase * old = root -> tree_ptr; +# ifndef __GC + // First check for the case in which everything is uniquely + // referenced. In that case we can do this destructively. + charT * charT_ptr = my_rope::fetch_ptr(old, pos); + if (0 != charT_ptr) { + *charT_ptr = c; + return *this; + } +# endif + self_destruct_ptr left(my_rope::substring(old, 0, pos)); + self_destruct_ptr right(my_rope::substring(old, pos+1, old -> size)); + self_destruct_ptr result_left(my_rope::destr_concat_char_iter(left, &c, 1)); +# ifndef __GC + __stl_assert(left == result_left || 1 == result_left -> refcount); +# endif + RopeBase * result = + my_rope::concat(result_left, right); +# ifndef __GC + __stl_assert(1 <= result -> refcount); + RopeBase::unref(old); +# endif + root -> tree_ptr = result; + return *this; +} + +template <class charT, class Alloc> +inline __rope_charT_ref_proxy<charT, Alloc>::operator charT () const +{ + if (current_valid) { + return current; + } else { + return my_rope::fetch(root->tree_ptr, pos); + } +} +template <class charT, class Alloc> +__rope_charT_ptr_proxy<charT, Alloc> +__rope_charT_ref_proxy<charT, Alloc>::operator& () const { + return __rope_charT_ptr_proxy<charT, Alloc>(*this); +} + +template <class charT, class Alloc> +rope<charT, Alloc>::rope(size_t n, charT c) +{ + RopeBase * result; + const size_t exponentiate_threshold = 32; + size_t exponent; + size_t rest; + charT *rest_buffer; + RopeBase * remainder; + + if (0 == n) { tree_ptr = 0; return; } + exponent = n / exponentiate_threshold; + rest = n % exponentiate_threshold; + if (0 == rest) { + remainder = 0; + } else { + rest_buffer = (charT *)Alloc::allocate(rounded_up_size(rest)); + uninitialized_fill_n(rest_buffer, rest, c); + __cond_store_eos(rest_buffer[rest]); + __STL_TRY + remainder = RopeLeaf_from_char_ptr(rest_buffer, rest); + __STL_UNWIND(RopeBase::free_string(rest_buffer, rest)) + } + __STL_TRY + if (exponent != 0) { + charT * base_buffer = + (charT *)Alloc::allocate( + rounded_up_size(exponentiate_threshold)); + self_destruct_ptr base_leaf; + uninitialized_fill_n(base_buffer, exponentiate_threshold, c); + __cond_store_eos(base_buffer[exponentiate_threshold]); + __STL_TRY + base_leaf = RopeLeaf_from_char_ptr(base_buffer, + exponentiate_threshold); + __STL_UNWIND(RopeBase::free_string(base_buffer, exponentiate_threshold)) + if (1 == exponent) { + result = base_leaf; +# ifndef __GC + __stl_assert(1 == result -> refcount); + result -> refcount = 2; // will be decremented when base_leaf disappears +# endif + } else { + result = power((RopeBase *)base_leaf, exponent, concat_fn()); +# ifndef __GC + __stl_assert(0 == result -> refcount); + result -> refcount = 1; +# endif + } + if (0 != remainder) { +# ifndef __GC + __stl_assert(1 == remainder -> refcount); +# endif + result = tree_concat(result, remainder); + } + // All partial results computed by power must be used. + } else { + result = remainder; + } + __STL_UNWIND(unref(remainder)); +# ifndef __GC + __stl_assert(0 == result || 1 == result -> refcount); +# endif + tree_ptr = result; +} + +template<class charT, class Alloc> charT rope<charT,Alloc>::empty_c_str[1]; + +# ifdef _PTHREADS + template<class charT, class Alloc> + pthread_mutex_t rope<charT,Alloc>::swap_lock = PTHREAD_MUTEX_INITIALIZER; +# endif + +template<class charT, class Alloc> +const charT * rope<charT,Alloc>::c_str() const { + if (0 == tree_ptr) { + empty_c_str[0] = __eos((charT *)0); // Possibly redundant, + // but probably fast. + return empty_c_str; + } + __GC_CONST charT * old_c_string = tree_ptr -> c_string; + if (0 != old_c_string) return(old_c_string); + size_t s = size(); + charT * result = (charT *)Alloc::allocate((s + 1)*sizeof(charT)); + flatten(tree_ptr, result); + result[s] = __eos((charT *)0); +# ifdef __GC + tree_ptr -> c_string = result; +# else + if ((old_c_string = atomic_swap(&(tree_ptr -> c_string), result)) != 0) { + // It must have been added in the interim. Hence it had to have been + // separately allocated. Deallocate the old copy, since we just + // replaced it. + destroy(old_c_string, old_c_string + s + 1); + Alloc::deallocate(old_c_string, s + 1); + } +# endif + return(result); +} + +template<class charT, class Alloc> +const charT * rope<charT,Alloc>::replace_with_c_str() { + if (0 == tree_ptr) { + empty_c_str[0] = __eos((charT *)0); + return empty_c_str; + } + __GC_CONST charT * old_c_string = tree_ptr -> c_string; + if (RopeBase::leaf == tree_ptr -> tag && 0 != old_c_string) { + return(old_c_string); + } + size_t s = size(); + charT * result = (charT *)Alloc::allocate(rounded_up_size(s)); + flatten(tree_ptr, result); + result[s] = __eos((charT *)0); + tree_ptr -> unref_nonnil(); + tree_ptr = RopeLeaf_from_char_ptr(result, s); + return(result); +} + +// Algorithm specializations. More should be added. + +#ifndef _MSC_VER +// I couldn't get this to work with VC++ +template<class charT,class Alloc> +void +__rope_rotate(__rope_iterator<charT,Alloc> first, + __rope_iterator<charT,Alloc> middle, + __rope_iterator<charT,Alloc> last) { + __stl_assert(first.container() == middle.container() + && middle.container() == last.container()); + rope<charT,Alloc>& r(first.container()); + rope<charT,Alloc> prefix = r.substr(0, first.index()); + rope<charT,Alloc> suffix = r.substr(last.index(), r.size() - last.index()); + rope<charT,Alloc> part1 = r.substr(middle.index(), + last.index() - middle.index()); + rope<charT,Alloc> part2 = r.substr(first.index(), + middle.index() - first.index()); + r = prefix; + r += part1; + r += part2; + r += suffix; +} + +inline void rotate(__rope_iterator<char,__ALLOC> first, + __rope_iterator<char,__ALLOC> middle, + __rope_iterator<char,__ALLOC> last) { + __rope_rotate(first, middle, last); +} + +# if 0 +// Probably not useful for several reasons: +// - for SGIs 7.1 compiler and probably some others, +// this forces lots of rope<wchar_t, ...> instantiations, creating a +// code bloat and compile time problem. (Fixed in 7.2.) +// - wchar_t is 4 bytes wide on most UNIX platforms, making it unattractive +// for unicode strings. Unsigned short may be a better character +// type. +inline void rotate(__rope_iterator<wchar_t,__ALLOC> first, + __rope_iterator<wchar_t,__ALLOC> middle, + __rope_iterator<wchar_t,__ALLOC> last) { + __rope_rotate(first, middle, last); +} +# endif +#endif /* _MSC_VER */ diff --git a/libstdc++/stl/set.h b/libstdc++/stl/set.h new file mode 100644 index 0000000..6a79a62 --- /dev/null +++ b/libstdc++/stl/set.h @@ -0,0 +1,167 @@ +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#ifndef __SGI_STL_SET_H +#define __SGI_STL_SET_H + +#include <tree.h> + +#ifndef __STL_LIMITED_DEFAULT_TEMPLATES +template <class Key, class Compare = less<Key>, class Alloc = alloc> +#else +template <class Key, class Compare, class Alloc = alloc> +#endif +class set { +public: + // typedefs: + + typedef Key key_type; + typedef Key value_type; + typedef Compare key_compare; + typedef Compare value_compare; +private: + typedef rb_tree<key_type, value_type, + identity<value_type>, key_compare, Alloc> rep_type; + rep_type t; // red-black tree representing set +public: + typedef rep_type::const_pointer pointer; + typedef rep_type::const_reference reference; + typedef rep_type::const_reference const_reference; + typedef rep_type::const_iterator iterator; + typedef rep_type::const_iterator const_iterator; + typedef rep_type::const_reverse_iterator reverse_iterator; + typedef rep_type::const_reverse_iterator const_reverse_iterator; + typedef rep_type::size_type size_type; + typedef rep_type::difference_type difference_type; + + // allocation/deallocation + + set() : t(Compare()) {} + explicit set(const Compare& comp) : t(comp) {} + +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + set(InputIterator first, InputIterator last) + : t(Compare()) { t.insert_unique(first, last); } + + template <class InputIterator> + set(InputIterator first, InputIterator last, const Compare& comp) + : t(comp) { t.insert_unique(first, last); } +#else + set(const value_type* first, const value_type* last) + : t(Compare()) { t.insert_unique(first, last); } + set(const value_type* first, const value_type* last, const Compare& comp) + : t(comp) { t.insert_unique(first, last); } + + set(const_iterator first, const_iterator last) + : t(Compare()) { t.insert_unique(first, last); } + set(const_iterator first, const_iterator last, const Compare& comp) + : t(comp) { t.insert_unique(first, last); } +#endif /* __STL_MEMBER_TEMPLATES */ + + set(const set<Key, Compare, Alloc>& x) : t(x.t) {} + set<Key, Compare, Alloc>& operator=(const set<Key, Compare, Alloc>& x) { + t = x.t; + return *this; + } + + // accessors: + + key_compare key_comp() const { return t.key_comp(); } + value_compare value_comp() const { return t.key_comp(); } + iterator begin() const { return t.begin(); } + iterator end() const { return t.end(); } + reverse_iterator rbegin() const { return t.rbegin(); } + reverse_iterator rend() const { return t.rend(); } + bool empty() const { return t.empty(); } + size_type size() const { return t.size(); } + size_type max_size() const { return t.max_size(); } + void swap(set<Key, Compare, Alloc>& x) { t.swap(x.t); } + + // insert/erase + typedef pair<iterator, bool> pair_iterator_bool; + pair<iterator,bool> insert(const value_type& x) { + pair<rep_type::iterator, bool> p = t.insert_unique(x); + return pair<iterator, bool>(p.first, p.second); + } + iterator insert(iterator position, const value_type& x) { + return t.insert_unique((rep_type::iterator&)position, x); + } +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + void insert(InputIterator first, InputIterator last) { + t.insert_unique(first, last); + } +#else + void insert(const_iterator first, const_iterator last) { + t.insert_unique(first, last); + } + void insert(const value_type* first, const value_type* last) { + t.insert_unique(first, last); + } +#endif /* __STL_MEMBER_TEMPLATES */ + void erase(iterator position) { + t.erase((rep_type::iterator&)position); + } + size_type erase(const key_type& x) { + return t.erase(x); + } + void erase(iterator first, iterator last) { + t.erase((rep_type::iterator&)first, + (rep_type::iterator&)last); + } + void clear() { t.clear(); } + + // set operations: + + iterator find(const key_type& x) const { return t.find(x); } + size_type count(const key_type& x) const { return t.count(x); } + iterator lower_bound(const key_type& x) const { + return t.lower_bound(x); + } + iterator upper_bound(const key_type& x) const { + return t.upper_bound(x); + } + pair<iterator,iterator> equal_range(const key_type& x) const { + return t.equal_range(x); + } + friend bool operator==(const set&, const set&); + friend bool operator<(const set&, const set&); +}; + +template <class Key, class Compare, class Alloc> +inline bool operator==(const set<Key, Compare, Alloc>& x, + const set<Key, Compare, Alloc>& y) { + return x.t == y.t; +} + +template <class Key, class Compare, class Alloc> +inline bool operator<(const set<Key, Compare, Alloc>& x, + const set<Key, Compare, Alloc>& y) { + return x.t < y.t; +} + +#endif /* __SGI_STL_SET_H */ diff --git a/libstdc++/stl/slist.h b/libstdc++/stl/slist.h new file mode 100644 index 0000000..bb99920 --- /dev/null +++ b/libstdc++/stl/slist.h @@ -0,0 +1,729 @@ +/* + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef __SGI_STL_SLIST_H +#define __SGI_STL_SLIST_H + +#include <algobase.h> +#include <alloc.h> + +struct __slist_node_base +{ + __slist_node_base* next; +}; + +inline __slist_node_base* __slist_make_link(__slist_node_base* prev_node, + __slist_node_base* new_node) +{ + new_node->next = prev_node->next; + prev_node->next = new_node; + return new_node; +} + +inline __slist_node_base* __slist_previous(__slist_node_base* head, + const __slist_node_base* node) +{ + while (head && head->next != node) + head = head->next; + return head; +} + +inline const __slist_node_base* __slist_previous(const __slist_node_base* head, + const __slist_node_base* node) +{ + while (head && head->next != node) + head = head->next; + return head; +} + +inline void __slist_splice_after(__slist_node_base* pos, + __slist_node_base* before_first, + __slist_node_base* before_last) +{ + if (pos != before_first && pos != before_last) { + __slist_node_base* first = before_first->next; + __slist_node_base* after = pos->next; + before_first->next = before_last->next; + pos->next = first; + before_last->next = after; + } +} + +inline __slist_node_base* __slist_reverse(__slist_node_base* node) +{ + __slist_node_base* result = node; + node = node->next; + result->next = 0; + while(node) { + __slist_node_base* next = node->next; + node->next = result; + result = node; + node = next; + } + return result; +} + +template <class T> +struct __slist_node : public __slist_node_base +{ + T data; +}; + +struct __slist_iterator_base +{ + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef forward_iterator_tag iterator_category; + + __slist_node_base* node; + + __slist_iterator_base(__slist_node_base* x) : node(x) {} + void incr() { node = node->next; } + + bool operator==(const __slist_iterator_base& x) const { + return node == x.node; + } + bool operator!=(const __slist_iterator_base& x) const { + return node != x.node; + } +}; + +template <class T, class Ref> +struct __slist_iterator : public __slist_iterator_base +{ + typedef __slist_iterator<T, T&> iterator; + typedef __slist_iterator<T, const T&> const_iterator; + typedef __slist_iterator<T, Ref> self; + + typedef T value_type; + typedef value_type* pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef __slist_node<T> list_node; + + __slist_iterator(list_node* x) : __slist_iterator_base(x) {} + __slist_iterator() : __slist_iterator_base(0) {} + __slist_iterator(const iterator& x) : __slist_iterator_base(x.node) {} + + Ref operator*() const { return ((list_node*) node)->data; } + self& operator++() + { + incr(); + return *this; + } + self operator++(int) + { + self tmp = *this; + incr(); + return tmp; + } +}; + +inline ptrdiff_t* +distance_type(const __slist_iterator_base&) +{ + return 0; +} + +inline forward_iterator_tag +iterator_category(const __slist_iterator_base&) +{ + return forward_iterator_tag(); +} + +template <class T, class Ref> +inline T* +value_type(const __slist_iterator<T, Ref>&) { + return 0; +} + +inline size_t __slist_size(__slist_node_base* node) +{ + size_t result = 0; + for ( ; node != 0; node = node->next) + ++result; + return result; +} + +template <class T, class Alloc = alloc> +class slist +{ +public: + typedef T value_type; + typedef value_type* pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + typedef __slist_iterator<T, reference> iterator; + typedef __slist_iterator<T, const_reference> const_iterator; + +private: + typedef __slist_node<T> list_node; + typedef __slist_node_base list_node_base; + typedef __slist_iterator_base iterator_base; + typedef simple_alloc<list_node, Alloc> list_node_allocator; + + static list_node* create_node(const value_type& x) { + list_node* node = list_node_allocator::allocate(); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + construct(&node->data, x); + node->next = 0; + return node; +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + list_node_allocator::deallocate(node); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } + + static void destroy_node(list_node* node) { + destroy(&node->data); + list_node_allocator::deallocate(node); + } + + void fill_initialize(size_type n, const value_type& x) { + head.next = 0; +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + _insert_after_fill(&head, n, x); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + clear(); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } + +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + void range_initialize(InputIterator first, InputIterator last) { + head.next = 0; +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + _insert_after_range(&head, first, last); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + clear(); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } +#else /* __STL_MEMBER_TEMPLATES */ + void range_initialize(const value_type* first, const value_type* last) { + head.next = 0; +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + _insert_after_range(&head, first, last); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + clear(); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } + void range_initialize(const_iterator first, const_iterator last) { + head.next = 0; +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + _insert_after_range(&head, first, last); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + clear(); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } +#endif /* __STL_MEMBER_TEMPLATES */ + +private: + list_node_base head; + +public: + slist() { head.next = 0; } + + slist(size_type n, const value_type& x) { fill_initialize(n, x); } + slist(int n, const value_type& x) { fill_initialize(n, x); } + slist(long n, const value_type& x) { fill_initialize(n, x); } + explicit slist(size_type n) { fill_initialize(n, value_type()); } + +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + slist(InputIterator first, InputIterator last) { + range_initialize(first, last); + } + +#else /* __STL_MEMBER_TEMPLATES */ + slist(const_iterator first, const_iterator last) { + range_initialize(first, last); + } + slist(const value_type* first, const value_type* last) { + range_initialize(first, last); + } +#endif /* __STL_MEMBER_TEMPLATES */ + + slist(const slist& L) { range_initialize(L.begin(), L.end()); } + + slist& operator= (const slist& L); + + ~slist() { clear(); } + +public: + + iterator begin() { return iterator((list_node*)head.next); } + const_iterator begin() const { return const_iterator((list_node*)head.next);} + + iterator end() { return iterator(0); } + const_iterator end() const { return const_iterator(0); } + + size_type size() const { return __slist_size(head.next); } + + size_type max_size() const { return size_type(-1); } + + bool empty() const { return head.next == 0; } + + void swap(slist& L) + { + list_node_base* tmp = head.next; + head.next = L.head.next; + L.head.next = tmp; + } + +public: + friend bool operator==(const slist<T, Alloc>& L1, const slist<T, Alloc>& L2); + +public: + + reference front() { return ((list_node*) head.next)->data; } + const_reference front() const { return ((list_node*) head.next)->data; } + void push_front(const value_type& x) { + __slist_make_link(&head, create_node(x)); + } + void pop_front() { + list_node* node = (list_node*) head.next; + head.next = node->next; + destroy_node(node); + } + + iterator previous(const_iterator pos) { + return iterator((list_node*) __slist_previous(&head, pos.node)); + } + const_iterator previous(const_iterator pos) const { + return const_iterator((list_node*) __slist_previous(&head, pos.node)); + } + +private: + list_node* _insert_after(list_node_base* pos, const value_type& x) { + return (list_node*) (__slist_make_link(pos, create_node(x))); + } + + void _insert_after_fill(list_node_base* pos, + size_type n, const value_type& x) { + for (size_type i = 0; i < n; ++i) + pos = __slist_make_link(pos, create_node(x)); + } + +#ifdef __STL_MEMBER_TEMPLATES + template <class InIter> + void _insert_after_range(list_node_base* pos, InIter first, InIter last) { + while (first != last) { + pos = __slist_make_link(pos, create_node(*first)); + ++first; + } + } +#else /* __STL_MEMBER_TEMPLATES */ + void _insert_after_range(list_node_base* pos, + const_iterator first, const_iterator last) { + while (first != last) { + pos = __slist_make_link(pos, create_node(*first)); + ++first; + } + } + void _insert_after_range(list_node_base* pos, + const value_type* first, const value_type* last) { + while (first != last) { + pos = __slist_make_link(pos, create_node(*first)); + ++first; + } + } +#endif /* __STL_MEMBER_TEMPLATES */ + + void erase_after(list_node_base* pos) { + list_node* next = (list_node*) (pos->next); + pos->next = next->next; + destroy_node(next); + } + + void erase_after(list_node_base* before_first, list_node_base* last_node) { + list_node* cur = (list_node*) (before_first->next); + while (cur != last_node) { + list_node* tmp = cur; + cur = (list_node*) cur->next; + destroy_node(tmp); + } + before_first->next = last_node; + } + + +public: + + iterator insert_after(iterator pos, const value_type& x) { + return iterator(_insert_after(pos.node, x)); + } + + iterator insert_after(iterator pos) { + return insert_after(pos, value_type()); + } + + void insert_after(iterator pos, size_type n, const value_type& x) { + _insert_after_fill(pos.node, n, x); + } + void insert_after(iterator pos, int n, const value_type& x) { + _insert_after_fill(pos.node, (size_type) n, x); + } + void insert_after(iterator pos, long n, const value_type& x) { + _insert_after_fill(pos.node, (size_type) n, x); + } + +#ifdef __STL_MEMBER_TEMPLATES + template <class InIter> + void insert_after(iterator pos, InIter first, InIter last) { + _insert_after_range(pos.node, first, last); + } +#else /* __STL_MEMBER_TEMPLATES */ + void insert_after(iterator pos, const_iterator first, const_iterator last) { + _insert_after_range(pos.node, first, last); + } + void insert_after(iterator pos, + const value_type* first, const value_type* last) { + _insert_after_range(pos.node, first, last); + } +#endif /* __STL_MEMBER_TEMPLATES */ + + iterator insert(iterator pos, const value_type& x) { + return iterator(_insert_after(__slist_previous(&head, pos.node), x)); + } + + iterator insert(iterator pos) { + return iterator(_insert_after(__slist_previous(&head, pos.node), + value_type())); + } + + void insert(iterator pos, size_type n, const value_type& x) { + _insert_after_fill(__slist_previous(&head, pos.node), n, x); + } + void insert(iterator pos, int n, const value_type& x) { + _insert_after_fill(__slist_previous(&head, pos.node), (size_type) n, x); + } + void insert(iterator pos, long n, const value_type& x) { + _insert_after_fill(__slist_previous(&head, pos.node), (size_type) n, x); + } + +#ifdef __STL_MEMBER_TEMPLATES + template <class InIter> + void insert(iterator pos, InIter first, InIter last) { + _insert_after_range(__slist_previous(&head, pos.node), first, last); + } +#else /* __STL_MEMBER_TEMPLATES */ + void insert(iterator pos, const_iterator first, const_iterator last) { + _insert_after_range(__slist_previous(&head, pos.node), first, last); + } + void insert(iterator pos, const value_type* first, const value_type* last) { + _insert_after_range(__slist_previous(&head, pos.node), first, last); + } +#endif /* __STL_MEMBER_TEMPLATES */ + + +public: + void erase_after(iterator pos) { erase_after(pos.node); } + void erase_after(iterator before_first, iterator last) { + erase_after(before_first.node, last.node); + } + + void erase(iterator pos) { erase_after(__slist_previous(&head, pos.node)); } + void erase(iterator first, iterator last) { + erase_after(__slist_previous(&head, first.node), last.node); + } + + void resize(size_type new_size, const T& x); + void resize(size_type new_size) { resize(new_size, T()); } + void clear() { erase_after(&head, 0); } + +public: + // Moves the range [before_first + 1, before_last + 1) to *this, + // inserting it immediately after pos. This is constant time. + void splice_after(iterator pos, + iterator before_first, iterator before_last) + { + if (before_first != before_last) + __slist_splice_after(pos.node, before_first.node, before_last.node); + } + + // Moves the element that follows prev to *this, inserting it immediately + // after pos. This is constant time. + void splice_after(iterator pos, iterator prev) + { + __slist_splice_after(pos.node, prev.node, prev.node->next); + } + + + // Linear in distance(begin(), pos), and linear in L.size(). + void splice(iterator pos, slist& L) { + if (L.head.next) + __slist_splice_after(__slist_previous(&head, pos.node), + &L.head, + __slist_previous(&L.head, 0)); + } + + // Linear in distance(begin(), pos), and in distance(L.begin(), i). + void splice(iterator pos, slist& L, iterator i) { + __slist_splice_after(__slist_previous(&head, pos.node), + __slist_previous(&L.head, i.node), + i.node); + } + + // Linear in distance(begin(), pos), in distance(L.begin(), first), + // and in distance(first, last). + void splice(iterator pos, slist& L, iterator first, iterator last) + { + if (first != last) + __slist_splice_after(__slist_previous(&head, pos.node), + __slist_previous(&L.head, first.node), + __slist_previous(first.node, last.node)); + } + +public: + void reverse() { if (head.next) head.next = __slist_reverse(head.next); } + + void remove(const T& val); + void unique(); + void merge(slist& L); + void sort(); + +#ifdef __STL_MEMBER_TEMPLATES + template <class Predicate> void remove_if(Predicate pred); + template <class BinaryPredicate> void unique(BinaryPredicate pred); + template <class StrictWeakOrdering> void merge(slist&, StrictWeakOrdering); + template <class StrictWeakOrdering> void sort(StrictWeakOrdering comp); +#endif /* __STL_MEMBER_TEMPLATES */ +}; + +template <class T, class Alloc> +slist<T, Alloc>& slist<T,Alloc>::operator=(const slist<T, Alloc>& L) +{ + if (&L != this) { + list_node_base* p1 = &head; + list_node* n1 = (list_node*) head.next; + const list_node* n2 = (const list_node*) L.head.next; + while (n1 && n2) { + n1->data = n2->data; + p1 = n1; + n1 = (list_node*) n1->next; + n2 = (const list_node*) n2->next; + } + if (n2 == 0) + erase_after(p1, 0); + else + _insert_after_range(p1, + const_iterator((list_node*)n2), const_iterator(0)); + } + return *this; +} + +template <class T, class Alloc> +bool operator==(const slist<T, Alloc>& L1, const slist<T, Alloc>& L2) +{ + typedef typename slist<T,Alloc>::list_node list_node; + list_node* n1 = (list_node*) L1.head.next; + list_node* n2 = (list_node*) L2.head.next; + while (n1 && n2 && n1->data == n2->data) { + n1 = (list_node*) n1->next; + n2 = (list_node*) n2->next; + } + return n1 == 0 && n2 == 0; +} + +template <class T, class Alloc> +inline bool operator<(const slist<T, Alloc>& L1, const slist<T, Alloc>& L2) +{ + return lexicographical_compare(L1.begin(), L1.end(), L2.begin(), L2.end()); +} + +template <class T, class Alloc> +void slist<T, Alloc>::resize(size_type len, const T& x) +{ + list_node_base* cur = &head; + while (cur->next != 0 && len > 0) { + --len; + cur = cur->next; + } + if (cur->next) + erase_after(cur, 0); + else + _insert_after_fill(cur, len, x); +} + +template <class T, class Alloc> +void slist<T,Alloc>::remove(const T& val) +{ + list_node_base* cur = &head; + while (cur && cur->next) { + if (((list_node*) cur->next)->data == val) + erase_after(cur); + else + cur = cur->next; + } +} + +template <class T, class Alloc> +void slist<T,Alloc>::unique() +{ + list_node_base* cur = head.next; + if (cur) { + while (cur->next) { + if (((list_node*)cur)->data == ((list_node*)(cur->next))->data) + erase_after(cur); + else + cur = cur->next; + } + } +} + +template <class T, class Alloc> +void slist<T,Alloc>::merge(slist<T,Alloc>& L) +{ + list_node_base* n1 = &head; + while (n1->next && L.head.next) { + if (((list_node*) L.head.next)->data < ((list_node*) n1->next)->data) + __slist_splice_after(n1, &L.head, L.head.next); + n1 = n1->next; + } + if (L.head.next) { + n1->next = L.head.next; + L.head.next = 0; + } +} + +template <class T, class Alloc> +void slist<T,Alloc>::sort() +{ + if (head.next && head.next->next) { + slist carry; + slist counter[64]; + int fill = 0; + while (!empty()) { + __slist_splice_after(&carry.head, &head, head.next); + int i = 0; + while (i < fill && !counter[i].empty()) { + counter[i].merge(carry); + carry.swap(counter[i]); + ++i; + } + carry.swap(counter[i]); + if (i == fill) + ++fill; + } + + for (int i = 1; i < fill; ++i) + counter[i].merge(counter[i-1]); + this->swap(counter[fill-1]); + } +} + +#ifdef __STL_MEMBER_TEMPLATES + +template <class T, class Alloc> +template <class Predicate> void slist<T,Alloc>::remove_if(Predicate pred) +{ + list_node_base* cur = &head; + while (cur->next) { + if (pred(((list_node*) cur->next)->data)) + erase_after(cur); + else + cur = cur->next; + } +} + +template <class T, class Alloc> template <class BinaryPredicate> +void slist<T,Alloc>::unique(BinaryPredicate pred) +{ + list_node* cur = (list_node*) head.next; + if (cur) { + while (cur->next) { + if (pred(((list_node*)cur)->data, ((list_node*)(cur->next))->data)) + erase_after(cur); + else + cur = (list_node*) cur->next; + } + } +} + +template <class T, class Alloc> template <class StrictWeakOrdering> +void slist<T,Alloc>::merge(slist<T,Alloc>& L, StrictWeakOrdering comp) +{ + list_node_base* n1 = &head; + while (n1->next && L.head.next) { + if (comp(((list_node*) L.head.next)->data, + ((list_node*) n1->next)->data)) + __slist_splice_after(n1, &L.head, L.head.next); + n1 = n1->next; + } + if (L.head.next) { + n1->next = L.head.next; + L.head.next = 0; + } +} + +template <class T, class Alloc> template <class StrictWeakOrdering> +void slist<T,Alloc>::sort(StrictWeakOrdering comp) +{ + if (head.next && head.next->next) { + slist carry; + slist counter[64]; + int fill = 0; + while (!empty()) { + __slist_splice_after(&carry.head, &head, head.next); + int i = 0; + while (i < fill && !counter[i].empty()) { + counter[i].merge(carry, comp); + carry.swap(counter[i]); + ++i; + } + carry.swap(counter[i]); + if (i == fill) + ++fill; + } + + for (int i = 1; i < fill; ++i) + counter[i].merge(counter[i-1], comp); + this->swap(counter[fill-1]); + } +} + +#endif /* __STL_MEMBER_TEMPLATES */ + +#endif /* __SGI_STL_SLIST_H */ diff --git a/libstdc++/stl/stack.h b/libstdc++/stl/stack.h new file mode 100644 index 0000000..cc025bb --- /dev/null +++ b/libstdc++/stl/stack.h @@ -0,0 +1,171 @@ +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#ifndef STACK_H +#define STACK_H + +#include <function.h> +#include <heap.h> +#include <vector.h> +#include <deque.h> + +#ifndef __STL_LIMITED_DEFAULT_TEMPLATES +template <class T, class Sequence = deque<T> > +#else +template <class T, class Sequence> +#endif +class stack { + friend bool operator==(const stack<T, Sequence>& x, + const stack<T, Sequence>& y); + friend bool operator<(const stack<T, Sequence>& x, + const stack<T, Sequence>& y); +public: + typedef typename Sequence::value_type value_type; + typedef typename Sequence::size_type size_type; +protected: + Sequence c; +public: + bool empty() const { return c.empty(); } + size_type size() const { return c.size(); } + value_type& top() { return c.back(); } + const value_type& top() const { return c.back(); } + void push(const value_type& x) { c.push_back(x); } + void pop() { c.pop_back(); } +}; + +template <class T, class Sequence> +bool operator==(const stack<T, Sequence>& x, const stack<T, Sequence>& y) { + return x.c == y.c; +} + +template <class T, class Sequence> +bool operator<(const stack<T, Sequence>& x, const stack<T, Sequence>& y) { + return x.c < y.c; +} + +#ifndef __STL_LIMITED_DEFAULT_TEMPLATES +template <class T, class Sequence = deque<T> > +#else +template <class T, class Sequence> +#endif +class queue { +friend bool operator==(const queue<T, Sequence>& x, const queue<T, Sequence>& y); +friend bool operator<(const queue<T, Sequence>& x, const queue<T, Sequence>& y); +public: + typedef typename Sequence::value_type value_type; + typedef typename Sequence::size_type size_type; +protected: + Sequence c; +public: + bool empty() const { return c.empty(); } + size_type size() const { return c.size(); } + value_type& front() { return c.front(); } + const value_type& front() const { return c.front(); } + value_type& back() { return c.back(); } + const value_type& back() const { return c.back(); } + void push(const value_type& x) { c.push_back(x); } + void pop() { c.pop_front(); } +}; + +template <class T, class Sequence> +bool operator==(const queue<T, Sequence>& x, const queue<T, Sequence>& y) { + return x.c == y.c; +} + +template <class T, class Sequence> +bool operator<(const queue<T, Sequence>& x, const queue<T, Sequence>& y) { + return x.c < y.c; +} + +#ifndef __STL_LIMITED_DEFAULT_TEMPLATES +template <class T, class Sequence = vector<T>, + class Compare = less<typename Sequence::value_type> > +#else +template <class T, class Sequence, class Compare> +#endif +class priority_queue { +public: + typedef typename Sequence::value_type value_type; + typedef typename Sequence::size_type size_type; +protected: + Sequence c; + Compare comp; +public: + priority_queue() : c() {} + explicit priority_queue(const Compare& x) : c(), comp(x) {} + +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + priority_queue(InputIterator first, InputIterator last, const Compare& x) + : c(first, last), comp(x) { make_heap(c.begin(), c.end(), comp); } + template <class InputIterator> + priority_queue(InputIterator first, InputIterator last) + : c(first, last) { make_heap(c.begin(), c.end(), comp); } +#else /* __STL_MEMBER_TEMPLATES */ + priority_queue(const value_type* first, const value_type* last, + const Compare& x) : c(first, last), comp(x) { + make_heap(c.begin(), c.end(), comp); + } + priority_queue(const value_type* first, const value_type* last) + : c(first, last) { make_heap(c.begin(), c.end(), comp); } +#endif /* __STL_MEMBER_TEMPLATES */ + + bool empty() const { return c.empty(); } + size_type size() const { return c.size(); } + const value_type& top() const { return c.front(); } + void push(const value_type& x) { +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + c.push_back(x); + push_heap(c.begin(), c.end(), comp); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + c.clear(); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } + void pop() { +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + pop_heap(c.begin(), c.end(), comp); + c.pop_back(); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + c.clear(); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } +}; + +// no equality is provided + +#endif diff --git a/libstdc++/stl/stl_config.h b/libstdc++/stl/stl_config.h new file mode 100644 index 0000000..fa29fdd --- /dev/null +++ b/libstdc++/stl/stl_config.h @@ -0,0 +1,170 @@ +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * Copyright (c) 1997 + * Silicon Graphics + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef __STL_CONFIG_H +# define __STL_CONFIG_H + +// What this file does. +// (1) Defines bool, true, and false if the compiler doesn't do so already. +// (2) Defines __STL_NO_DRAND48 if the compiler's standard library does +// not support the drand48() function. +// (3) Defines __STL_STATIC_TEMPLATE_MEMBER_BUG if the compiler can't +// handle static members of template classes. +// (4) Defines 'typename' as a null macro if the compiler does not support +// the typename keyword. +// (5) Defines __STL_CLASS_PARTIAL_SPECIALIZATION if the compiler +// supports partial specialization of template classes. +// (6) Defines __STL_MEMBER_TEMPLATES if the compiler supports +// template members of classes. +// (7) Defines 'explicit' as a null macro if the compiler does not support +// the explicit keyword. +// (8) Defines __STL_LIMITED_DEFAULT_TEMPLATES if the compiler is +// unable to handle default template parameters that depend on +// previous template parameters. +// (9) Defines __STL_NON_TYPE_TMPL_PARAM_BUG if the compiler has +// trouble performing function template argument deduction for +// non-type template parameters. +// (10) Defines __STL_USE_EXCEPTIONS if the compiler (in the current +// compilation mode) supports exceptions. +// (11) Defines __STL_SGI_THREADS if this is being compiled on an SGI +// compiler, and if the user hasn't selected pthreads or no threads +// instead. +// (12) Defines __STL_WIN32THREADS if this is being compiled on a +// WIN32 compiler in multithreaded mode. +// (13) Defines __stl_assert either as a test or as a null macro, +// depending on whether or not __STL_ASSERTIONS is defined. + +# if defined(__sgi) && !defined(__GNUC__) +# if !defined(_BOOL) +# define __STL_NEED_BOOL +# endif +# if !defined(_TYPENAME_IS_KEYWORD) +# define __STL_NEED_TYPENAME +# endif +# ifdef _PARTIAL_SPECIALIZATION_OF_CLASS_TEMPLATES +# define __STL_CLASS_PARTIAL_SPECIALIZATION +# endif +# ifdef _MEMBER_TEMPLATES +# define __STL_MEMBER_TEMPLATES +# endif +# if !defined(_EXPLICIT_IS_KEYWORD) +# define __STL_NEED_EXPLICIT +# endif +# ifdef __EXCEPTIONS +# define __STL_USE_EXCEPTIONS +# endif +# if !defined(_NOTHREADS) && !defined(_PTHREADS) +# define __STL_SGI_THREADS +# endif +# endif + +# ifdef __GNUC__ +# if 0 && (__GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)) +# define __STL_STATIC_TEMPLATE_MEMBER_BUG +# define __STL_NEED_TYPENAME +# define __STL_NEED_EXPLICIT +# else +# define __STL_CLASS_PARTIAL_SPECIALIZATION +# endif +# ifdef __EXCEPTIONS +# define __STL_USE_EXCEPTIONS +# endif +# endif + +# if defined(__SUNPRO_CC) +# define __STL_NEED_BOOL +# define __STL_NEED_TYPENAME +# define __STL_NEED_EXPLICIT +# define __STL_USE_EXCEPTIONS +# endif + +# if defined(__COMO__) +# define __STL_MEMBER_TEMPLATES +# define __STL_CLASS_PARTIAL_SPECIALIZATION +# define __STL_USE_EXCEPTIONS +# endif + +# if defined(_MSC_VER) +# if _MSC_VER > 1000 +# include <yvals.h> +# else +# define __STL_NEED_BOOL +# endif +# define __STL_NO_DRAND48 +# define __STL_NEED_TYPENAME +# if _MSC_VER < 1100 +# define __STL_NEED_EXPLICIT +# endif +# define __STL_NON_TYPE_TMPL_PARAM_BUG +# ifdef _CPPUNWIND +# define __STL_USE_EXCEPTIONS +# endif +# ifdef _MT +# define __STL_WIN32THREADS +# endif +# endif + +# if defined(__BORLANDC__) +# define __STL_NO_DRAND48 +# define __STL_NEED_TYPENAME +# define __STL_LIMITED_DEFAULT_TEMPLATES +# define __STL_NON_TYPE_TMPL_PARAM_BUG +# ifdef _CPPUNWIND +# define __STL_USE_EXCEPTIONS +# endif +# ifdef __MT__ +# define __STL_WIN32THREADS +# endif +# endif + + +# if defined(__STL_NEED_BOOL) + typedef int bool; +# define true 1 +# define false 0 +# undef __STL_NEED_BOOL +# endif + +# ifdef __STL_NEED_TYPENAME +# define typename +# undef __STL_NEED_TYPENAME +# endif + +# ifdef __STL_NEED_EXPLICIT +# define explicit +# undef __STL_NEED_EXPLICIT +# endif + +#ifdef __STL_ASSERTIONS +# include <stdio.h> +# define __stl_assert(expr) \ + if (!(expr)) { fprintf(stderr, "%s:%d STL assertion failure: %s\n", \ + __FILE__, __LINE__, # expr); abort(); } +#else +# define __stl_assert(expr) +#endif + +#endif /* __STL_CONFIG_H */ diff --git a/libstdc++/stl/tempbuf.h b/libstdc++/stl/tempbuf.h new file mode 100644 index 0000000..18d9952 --- /dev/null +++ b/libstdc++/stl/tempbuf.h @@ -0,0 +1,121 @@ +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#ifndef __SGI_STL_TEMPBUF_H +#define __SGI_STL_TEMPBUF_H + +#include <limits.h> +#include <stddef.h> +#include <stdlib.h> +#include <pair.h> +#include <type_traits.h> + +template <class T> +pair<T*, ptrdiff_t> get_temporary_buffer(ptrdiff_t len, T*) { + if (len > ptrdiff_t(INT_MAX / sizeof(T))) + len = INT_MAX / sizeof(T); + + while (len > 0) { + T* tmp = (T*) malloc((size_t)len * sizeof(T)); + if (tmp != 0) + return pair<T*, ptrdiff_t>(tmp, len); + len /= 2; + } + + return pair<T*, ptrdiff_t>((T*)0, 0); +} + +template <class T> +void return_temporary_buffer(T* p) { + free(p); +} + +template <class ForwardIterator, + class T /* = iterator_traits<ForwardIterator>::value_type */> +class temporary_buffer { +private: + ptrdiff_t original_len; + ptrdiff_t len; + T* buffer; + + void allocate_buffer() { + original_len = len; + buffer = 0; + + if (len > (ptrdiff_t)(INT_MAX / sizeof(T))) + len = INT_MAX / sizeof(T); + + while (len > 0) { + buffer = (T*) malloc(len * sizeof(T)); + if (buffer) + break; + len /= 2; + } + } + + void initialize_buffer(const T&, __true_type) {} + void initialize_buffer(const T& val, __false_type) { + uninitialized_fill_n(buffer, len, val); + } + +public: + ptrdiff_t size() const { return len; } + ptrdiff_t requested_size() const { return original_len; } + T* begin() { return buffer; } + T* end() { return buffer + len; } + + temporary_buffer(ForwardIterator first, ForwardIterator last) { +#ifdef __STL_USE_EXCEPTIONS + try { +#endif + len = 0; + distance(first, last, len); + allocate_buffer(); + if (len > 0) + initialize_buffer(*first, + __type_traits<T>::has_trivial_default_constructor()); +#ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + free(buffer); + buffer = 0; + len = 0; + throw; + } +#endif + } + + ~temporary_buffer() { + destroy(buffer, buffer + len); + free(buffer); + } + +private: + temporary_buffer(const temporary_buffer&) {} + void operator=(const temporary_buffer&) {} +}; + +#endif /* __SGI_STL_TEMPBUF_H */ diff --git a/libstdc++/stl/tree.h b/libstdc++/stl/tree.h new file mode 100644 index 0000000..0429c1a --- /dev/null +++ b/libstdc++/stl/tree.h @@ -0,0 +1,1085 @@ +/* + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + */ + +#ifndef __SGI_STL_TREE_H +#define __SGI_STL_TREE_H + +/* + +Red-black tree class, designed for use in implementing STL +associative containers (set, multiset, map, and multimap). The +insertion and deletion algorithms are based on those in Cormen, +Leiserson, and Rivest, Introduction to Algorithms (MIT Press, 1990), +except that + +(1) the header cell is maintained with links not only to the root +but also to the leftmost node of the tree, to enable constant time +begin(), and to the rightmost node of the tree, to enable linear time +performance when used with the generic set algorithms (set_union, +etc.); + +(2) when a node being deleted has two children its successor node is +relinked into its place, rather than copied, so that the only +iterators invalidated are those referring to the deleted node. + +*/ + +#include <stddef.h> +#include <algobase.h> +#include <iterator.h> +#include <alloc.h> + + +typedef bool __rb_tree_color_type; +const __rb_tree_color_type __rb_tree_red = false; +const __rb_tree_color_type __rb_tree_black = true; + +struct __rb_tree_node_base +{ + typedef __rb_tree_color_type color_type; + typedef __rb_tree_node_base* base_ptr; + + color_type color; + base_ptr parent; + base_ptr left; + base_ptr right; + + static base_ptr minimum(base_ptr x) + { + while (x->left != 0) x = x->left; + return x; + } + + static base_ptr maximum(base_ptr x) + { + while (x->right != 0) x = x->right; + return x; + } +}; + +template <class Value> +struct __rb_tree_node : public __rb_tree_node_base +{ + typedef __rb_tree_node<Value>* link_type; + Value value_field; +}; + + +struct __rb_tree_base_iterator +{ + typedef __rb_tree_node_base::base_ptr base_ptr; + typedef bidirectional_iterator_tag iterator_category; + typedef ptrdiff_t difference_type; + base_ptr node; + + void increment() + { + if (node->right != 0) { + node = node->right; + while (node->left != 0) + node = node->left; + } + else { + base_ptr y = node->parent; + while (node == y->right) { + node = y; + y = y->parent; + } + if (node->right != y) + node = y; + } + } + + void decrement() + { + if (node->color == __rb_tree_red && + node->parent->parent == node) + node = node->right; + else if (node->left != 0) { + base_ptr y = node->left; + while (y->right != 0) + y = y->right; + node = y; + } + else { + base_ptr y = node->parent; + while (node == y->left) { + node = y; + y = y->parent; + } + node = y; + } + } +}; + +template <class Value, class Ref> +struct __rb_tree_iterator : public __rb_tree_base_iterator +{ + typedef Value value_type; + typedef Value& reference; + typedef const Value& const_reference; + typedef Value* pointer; + typedef __rb_tree_iterator<Value, reference> iterator; + typedef __rb_tree_iterator<Value, const_reference> const_iterator; + typedef __rb_tree_iterator<Value, Ref> self; + typedef __rb_tree_node<Value>* link_type; + + __rb_tree_iterator() {} + __rb_tree_iterator(link_type x) { node = x; } + __rb_tree_iterator(const iterator& it) { node = it.node; } + + Ref operator*() const { return link_type(node)->value_field; } + + self& operator++() { increment(); return *this; } + self operator++(int) { + self tmp = *this; + increment(); + return tmp; + } + + self& operator--() { decrement(); return *this; } + self operator--(int) { + self tmp = *this; + decrement(); + return tmp; + } +}; + +inline bool operator==(const __rb_tree_base_iterator& x, + const __rb_tree_base_iterator& y) { + return x.node == y.node; +} + +inline bool operator!=(const __rb_tree_base_iterator& x, + const __rb_tree_base_iterator& y) { + return x.node != y.node; +} + +inline bidirectional_iterator_tag +iterator_category(const __rb_tree_base_iterator&) { + return bidirectional_iterator_tag(); +} + +inline __rb_tree_base_iterator::difference_type* +distance_type(const __rb_tree_base_iterator&) { + return (__rb_tree_base_iterator::difference_type*) 0; +} + +template <class Value, class Ref> +inline Value* value_type(const __rb_tree_iterator<Value, Ref>&) { + return (Value*) 0; +} + +inline void +__rb_tree_rotate_left(__rb_tree_node_base* x, __rb_tree_node_base*& root) +{ + __rb_tree_node_base* y = x->right; + x->right = y->left; + if (y->left !=0) + y->left->parent = x; + y->parent = x->parent; + + if (x == root) + root = y; + else if (x == x->parent->left) + x->parent->left = y; + else + x->parent->right = y; + y->left = x; + x->parent = y; +} + +inline void +__rb_tree_rotate_right(__rb_tree_node_base* x, __rb_tree_node_base*& root) +{ + __rb_tree_node_base* y = x->left; + x->left = y->right; + if (y->right != 0) + y->right->parent = x; + y->parent = x->parent; + + if (x == root) + root = y; + else if (x == x->parent->right) + x->parent->right = y; + else + x->parent->left = y; + y->right = x; + x->parent = y; +} + +inline void +__rb_tree_rebalance(__rb_tree_node_base* x, __rb_tree_node_base*& root) +{ + x->color = __rb_tree_red; + while (x != root && x->parent->color == __rb_tree_red) { + if (x->parent == x->parent->parent->left) { + __rb_tree_node_base* y = x->parent->parent->right; + if (y && y->color == __rb_tree_red) { + x->parent->color = __rb_tree_black; + y->color = __rb_tree_black; + x->parent->parent->color = __rb_tree_red; + x = x->parent->parent; + } + else { + if (x == x->parent->right) { + x = x->parent; + __rb_tree_rotate_left(x, root); + } + x->parent->color = __rb_tree_black; + x->parent->parent->color = __rb_tree_red; + __rb_tree_rotate_right(x->parent->parent, root); + } + } + else { + __rb_tree_node_base* y = x->parent->parent->left; + if (y && y->color == __rb_tree_red) { + x->parent->color = __rb_tree_black; + y->color = __rb_tree_black; + x->parent->parent->color = __rb_tree_red; + x = x->parent->parent; + } + else { + if (x == x->parent->left) { + x = x->parent; + __rb_tree_rotate_right(x, root); + } + x->parent->color = __rb_tree_black; + x->parent->parent->color = __rb_tree_red; + __rb_tree_rotate_left(x->parent->parent, root); + } + } + } + root->color = __rb_tree_black; +} + +inline __rb_tree_node_base* +__rb_tree_rebalance_for_erase(__rb_tree_node_base* z, + __rb_tree_node_base*& root, + __rb_tree_node_base*& leftmost, + __rb_tree_node_base*& rightmost) +{ + __rb_tree_node_base* y = z; + __rb_tree_node_base* x = 0; + __rb_tree_node_base* x_parent = 0; + if (y->left == 0) // z has at most one non-null child. y == z. + x = y->right; // x might be null. + else + if (y->right == 0) // z has exactly one non-null child. y == z. + x = y->left; // x is not null. + else { // z has two non-null children. Set y to + y = y->right; // z's successor. x might be null. + while (y->left != 0) + y = y->left; + x = y->right; + } + if (y != z) { // relink y in place of z. y is z's successor + z->left->parent = y; + y->left = z->left; + if (y != z->right) { + x_parent = y->parent; + if (x) x->parent = y->parent; + y->parent->left = x; // y must be a left child + y->right = z->right; + z->right->parent = y; + } + else + x_parent = y; + if (root == z) + root = y; + else if (z->parent->left == z) + z->parent->left = y; + else + z->parent->right = y; + y->parent = z->parent; + ::swap(y->color, z->color); + y = z; + // y now points to node to be actually deleted + } + else { // y == z + x_parent = y->parent; + if (x) x->parent = y->parent; + if (root == z) + root = x; + else + if (z->parent->left == z) + z->parent->left = x; + else + z->parent->right = x; + if (leftmost == z) + if (z->right == 0) // z->left must be null also + leftmost = z->parent; + // makes leftmost == header if z == root + else + leftmost = __rb_tree_node_base::minimum(x); + if (rightmost == z) + if (z->left == 0) // z->right must be null also + rightmost = z->parent; + // makes rightmost == header if z == root + else // x == z->left + rightmost = __rb_tree_node_base::maximum(x); + } + if (y->color != __rb_tree_red) { + while (x != root && (x == 0 || x->color == __rb_tree_black)) + if (x == x_parent->left) { + __rb_tree_node_base* w = x_parent->right; + if (w->color == __rb_tree_red) { + w->color = __rb_tree_black; + x_parent->color = __rb_tree_red; + __rb_tree_rotate_left(x_parent, root); + w = x_parent->right; + } + if ((w->left == 0 || w->left->color == __rb_tree_black) && + (w->right == 0 || w->right->color == __rb_tree_black)) { + w->color = __rb_tree_red; + x = x_parent; + x_parent = x_parent->parent; + } else { + if (w->right == 0 || w->right->color == __rb_tree_black) { + if (w->left) w->left->color = __rb_tree_black; + w->color = __rb_tree_red; + __rb_tree_rotate_right(w, root); + w = x_parent->right; + } + w->color = x_parent->color; + x_parent->color = __rb_tree_black; + if (w->right) w->right->color = __rb_tree_black; + __rb_tree_rotate_left(x_parent, root); + break; + } + } else { // same as above, with right <-> left. + __rb_tree_node_base* w = x_parent->left; + if (w->color == __rb_tree_red) { + w->color = __rb_tree_black; + x_parent->color = __rb_tree_red; + __rb_tree_rotate_right(x_parent, root); + w = x_parent->left; + } + if ((w->right == 0 || w->right->color == __rb_tree_black) && + (w->left == 0 || w->left->color == __rb_tree_black)) { + w->color = __rb_tree_red; + x = x_parent; + x_parent = x_parent->parent; + } else { + if (w->left == 0 || w->left->color == __rb_tree_black) { + if (w->right) w->right->color = __rb_tree_black; + w->color = __rb_tree_red; + __rb_tree_rotate_left(w, root); + w = x_parent->left; + } + w->color = x_parent->color; + x_parent->color = __rb_tree_black; + if (w->left) w->left->color = __rb_tree_black; + __rb_tree_rotate_right(x_parent, root); + break; + } + } + if (x) x->color = __rb_tree_black; + } + return y; +} + +template <class Key, class Value, class KeyOfValue, class Compare, + class Alloc = alloc> +class rb_tree { +protected: + typedef void* void_pointer; + typedef __rb_tree_node_base* base_ptr; + typedef __rb_tree_node<Value> rb_tree_node; + typedef simple_alloc<rb_tree_node, Alloc> rb_tree_node_allocator; + typedef __rb_tree_color_type color_type; +public: + typedef Key key_type; + typedef Value value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef rb_tree_node* link_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; +protected: + link_type get_node() { return rb_tree_node_allocator::allocate(); } + void put_node(link_type p) { rb_tree_node_allocator::deallocate(p); } + + link_type create_node(const value_type& x) { + link_type tmp = get_node(); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + construct(&tmp->value_field, x); + return tmp; +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + put_node(tmp); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } + + link_type clone_node(link_type x) { + link_type tmp = create_node(x->value_field); + tmp->color = x->color; + tmp->left = 0; + tmp->right = 0; + return tmp; + } + + void destroy_node(link_type p) { + destroy(&p->value_field); + put_node(p); + } + +protected: + size_type node_count; // keeps track of size of tree + link_type header; + Compare key_compare; + + link_type& root() const { return (link_type&) header->parent; } + link_type& leftmost() const { return (link_type&) header->left; } + link_type& rightmost() const { return (link_type&) header->right; } + + static link_type& left(link_type x) { return (link_type&)(x->left); } + static link_type& right(link_type x) { return (link_type&)(x->right); } + static link_type& parent(link_type x) { return (link_type&)(x->parent); } + static reference value(link_type x) { return x->value_field; } + static const Key& key(link_type x) { return KeyOfValue()(value(x)); } + static color_type& color(link_type x) { return (color_type&)(x->color); } + + static link_type& left(base_ptr x) { return (link_type&)(x->left); } + static link_type& right(base_ptr x) { return (link_type&)(x->right); } + static link_type& parent(base_ptr x) { return (link_type&)(x->parent); } + static reference value(base_ptr x) { return ((link_type)x)->value_field; } + static const Key& key(base_ptr x) { return KeyOfValue()(value(link_type(x)));} + static color_type& color(base_ptr x) { return (color_type&)(link_type(x)->color); } + + static link_type minimum(link_type x) { + return (link_type) __rb_tree_node_base::minimum(x); + } + static link_type maximum(link_type x) { + return (link_type) __rb_tree_node_base::maximum(x); + } + +public: + typedef __rb_tree_iterator<value_type, reference> iterator; + typedef __rb_tree_iterator<value_type, const_reference> const_iterator; + + typedef reverse_bidirectional_iterator<iterator, value_type, reference, + difference_type> + reverse_iterator; + typedef reverse_bidirectional_iterator<const_iterator, value_type, + const_reference, difference_type> + const_reverse_iterator; +private: + iterator __insert(base_ptr x, base_ptr y, const value_type& v); + link_type __copy(link_type x, link_type p); + void __erase(link_type x); + void init() { + header = get_node(); + color(header) = __rb_tree_red; // used to distinguish header from + // root, in iterator.operator++ + root() = 0; + leftmost() = header; + rightmost() = header; + } +public: + // allocation/deallocation + rb_tree(const Compare& comp = Compare()) + : key_compare(comp), node_count(0) { init(); } + + rb_tree(const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& x) + : key_compare(x.key_compare), node_count(0) { + header = get_node(); + color(header) = __rb_tree_red; + if (x.root() == 0) { + root() = 0; + leftmost() = header; + rightmost() = header; + } + else { +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + root() = __copy(x.root(), header); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + put_node(header); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + leftmost() = minimum(root()); + rightmost() = maximum(root()); + } + node_count = x.node_count; + } + ~rb_tree() { + clear(); + put_node(header); + } + rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& + operator=(const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& x); + +public: + // accessors: + Compare key_comp() const { return key_compare; } + iterator begin() { return leftmost(); } + const_iterator begin() const { return leftmost(); } + iterator end() { return header; } + const_iterator end() const { return header; } + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + bool empty() const { return node_count == 0; } + size_type size() const { return node_count; } + size_type max_size() const { return size_type(-1); } + + void swap(rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& t) { + ::swap(header, t.header); + ::swap(node_count, t.node_count); + ::swap(key_compare, t.key_compare); + } + +public: + // insert/erase + pair<iterator,bool> insert_unique(const value_type& x); + iterator insert_equal(const value_type& x); + + iterator insert_unique(iterator position, const value_type& x); + iterator insert_equal(iterator position, const value_type& x); + +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + void insert_unique(InputIterator first, InputIterator last); + template <class InputIterator> + void insert_equal(InputIterator first, InputIterator last); +#else /* __STL_MEMBER_TEMPLATES */ + void insert_unique(const_iterator first, const_iterator last); + void insert_unique(const value_type* first, const value_type* last); + void insert_equal(const_iterator first, const_iterator last); + void insert_equal(const value_type* first, const value_type* last); +#endif /* __STL_MEMBER_TEMPLATES */ + + void erase(iterator position); + size_type erase(const key_type& x); + void erase(iterator first, iterator last); + void erase(const key_type* first, const key_type* last); + void clear() { + if (node_count != 0) { + __erase(root()); + leftmost() = header; + root() = 0; + rightmost() = header; + node_count = 0; + } + } + +public: + // set operations: + iterator find(const key_type& x); + const_iterator find(const key_type& x) const; + size_type count(const key_type& x) const; + iterator lower_bound(const key_type& x); + const_iterator lower_bound(const key_type& x) const; + iterator upper_bound(const key_type& x); + const_iterator upper_bound(const key_type& x) const; + pair<iterator,iterator> equal_range(const key_type& x); + pair<const_iterator, const_iterator> equal_range(const key_type& x) const; + +public: + // Debugging. + bool __rb_verify() const; +}; + +template <class Key, class Value, class KeyOfValue, class Compare, class Alloc> +inline bool operator==(const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& x, + const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& y) { + return x.size() == y.size() && equal(x.begin(), x.end(), y.begin()); +} + +template <class Key, class Value, class KeyOfValue, class Compare, class Alloc> +inline bool operator<(const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& x, + const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& y) { + return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); +} + +template <class Key, class Value, class KeyOfValue, class Compare, class Alloc> +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>:: +operator=(const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& x) { + if (this != &x) { + // Note that Key may be a constant type. + clear(); + node_count = 0; + key_compare = x.key_compare; + if (x.root() == 0) { + root() = 0; + leftmost() = header; + rightmost() = header; + } + else { + root() = __copy(x.root(), header); + leftmost() = minimum(root()); + rightmost() = maximum(root()); + node_count = x.node_count; + } + } + return *this; +} + +template <class Key, class Value, class KeyOfValue, class Compare, class Alloc> +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>:: +__insert(base_ptr x_, base_ptr y_, const Value& v) { + link_type x = (link_type) x_; + link_type y = (link_type) y_; + link_type z; + + if (y == header || x != 0 || key_compare(KeyOfValue()(v), key(y))) { + z = create_node(v); + left(y) = z; // also makes leftmost() = z when y == header + if (y == header) { + root() = z; + rightmost() = z; + } + else if (y == leftmost()) + leftmost() = z; // maintain leftmost() pointing to min node + } + else { + z = create_node(v); + right(y) = z; + if (y == rightmost()) + rightmost() = z; // maintain rightmost() pointing to max node + } + parent(z) = y; + left(z) = 0; + right(z) = 0; + __rb_tree_rebalance(z, header->parent); + ++node_count; + return iterator(z); +} + +template <class Key, class Value, class KeyOfValue, class Compare, class Alloc> +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::insert_equal(const Value& v) +{ + link_type y = header; + link_type x = root(); + while (x != 0) { + y = x; + x = key_compare(KeyOfValue()(v), key(x)) ? left(x) : right(x); + } + return __insert(x, y, v); +} + + +template <class Key, class Value, class KeyOfValue, class Compare, class Alloc> +pair<rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator, bool> +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::insert_unique(const Value& v) +{ + link_type y = header; + link_type x = root(); + bool comp = true; + while (x != 0) { + y = x; + comp = key_compare(KeyOfValue()(v), key(x)); + x = comp ? left(x) : right(x); + } + iterator j = iterator(y); + if (comp) + if (j == begin()) + return pair<iterator,bool>(__insert(x, y, v), true); + else + --j; + if (key_compare(key(j.node), KeyOfValue()(v))) + return pair<iterator,bool>(__insert(x, y, v), true); + return pair<iterator,bool>(j, false); +} + + +template <class Key, class Val, class KeyOfValue, class Compare, class Alloc> +rb_tree<Key, Val, KeyOfValue, Compare, Alloc>::iterator +rb_tree<Key, Val, KeyOfValue, Compare, Alloc>::insert_unique(iterator position, + const Val& v) { + if (position.node == header->left) // begin() + if (size() > 0 && key_compare(KeyOfValue()(v), key(position.node))) + return __insert(position.node, position.node, v); + // first argument just needs to be non-null + else + return insert_unique(v).first; + else if (position.node == header) // end() + if (key_compare(key(rightmost()), KeyOfValue()(v))) + return __insert(0, rightmost(), v); + else + return insert_unique(v).first; + else { + iterator before = position; + --before; + if (key_compare(key(before.node), KeyOfValue()(v)) + && key_compare(KeyOfValue()(v), key(position.node))) + if (right(before.node) == 0) + return __insert(0, before.node, v); + else + return __insert(position.node, position.node, v); + // first argument just needs to be non-null + else + return insert_unique(v).first; + } +} + +template <class Key, class Val, class KeyOfValue, class Compare, class Alloc> +rb_tree<Key, Val, KeyOfValue, Compare, Alloc>::iterator +rb_tree<Key, Val, KeyOfValue, Compare, Alloc>::insert_equal(iterator position, + const Val& v) { + if (position.node == header->left) // begin() + if (size() > 0 && key_compare(KeyOfValue()(v), key(position.node))) + return __insert(position.node, position.node, v); + // first argument just needs to be non-null + else + return insert_equal(v); + else if (position.node == header) // end() + if (!key_compare(KeyOfValue()(v), key(rightmost()))) + return __insert(0, rightmost(), v); + else + return insert_equal(v); + else { + iterator before = position; + --before; + if (!key_compare(KeyOfValue()(v), key(before.node)) + && !key_compare(key(position.node), KeyOfValue()(v))) + if (right(before.node) == 0) + return __insert(0, before.node, v); + else + return __insert(position.node, position.node, v); + // first argument just needs to be non-null + else + return insert_equal(v); + } +} + +#ifdef __STL_MEMBER_TEMPLATES + +template <class K, class V, class KoV, class Cmp, class Al> template<class II> +void rb_tree<K, V, KoV, Cmp, Al>::insert_equal(II first, II last) { + for ( ; first != last; ++first) + insert_equal(*first); +} + +template <class K, class V, class KoV, class Cmp, class Al> template<class II> +void rb_tree<K, V, KoV, Cmp, Al>::insert_unique(II first, II last) { + for ( ; first != last; ++first) + insert_unique(*first); +} + +#else /* __STL_MEMBER_TEMPLATES */ + +template <class K, class V, class KoV, class Cmp, class Al> +void +rb_tree<K, V, KoV, Cmp, Al>::insert_equal(const V* first, const V* last) { + for ( ; first != last; ++first) + insert_equal(*first); +} + +template <class K, class V, class KoV, class Cmp, class Al> +void +rb_tree<K, V, KoV, Cmp, Al>::insert_equal(const_iterator first, + const_iterator last) { + for ( ; first != last; ++first) + insert_equal(*first); +} + +template <class K, class V, class KoV, class Cmp, class A> +void +rb_tree<K, V, KoV, Cmp, A>::insert_unique(const V* first, const V* last) { + for ( ; first != last; ++first) + insert_unique(*first); +} + +template <class K, class V, class KoV, class Cmp, class A> +void +rb_tree<K, V, KoV, Cmp, A>::insert_unique(const_iterator first, + const_iterator last) { + for ( ; first != last; ++first) + insert_unique(*first); +} + +#endif /* __STL_MEMBER_TEMPLATES */ + +template <class Key, class Value, class KeyOfValue, class Compare, class Alloc> +inline void +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::erase(iterator position) { + link_type y = (link_type) __rb_tree_rebalance_for_erase(position.node, + header->parent, + header->left, + header->right); + destroy_node(y); + --node_count; +} + +template <class Key, class Value, class KeyOfValue, class Compare, class Alloc> +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::size_type +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::erase(const Key& x) { + pair<iterator,iterator> p = equal_range(x); + size_type n = 0; + distance(p.first, p.second, n); + erase(p.first, p.second); + return n; +} + +template <class K, class V, class KeyOfValue, class Compare, class Alloc> +rb_tree<K, V, KeyOfValue, Compare, Alloc>::link_type +rb_tree<K, V, KeyOfValue, Compare, Alloc>::__copy(link_type x, link_type p) { + // structural copy. x and p must be non-null. + link_type top = clone_node(x); + top->parent = p; + +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + if (x->right) + top->right = __copy(right(x), top); + p = top; + x = left(x); + + while (x != 0) { + link_type y = clone_node(x); + p->left = y; + y->parent = p; + if (x->right) + y->right = __copy(right(x), y); + p = y; + x = left(x); + } +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + __erase(top); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + + return top; +} + +template <class Key, class Value, class KeyOfValue, class Compare, class Alloc> +void rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::__erase(link_type x) { + // erase without rebalancing + while (x != 0) { + __erase(right(x)); + link_type y = left(x); + destroy_node(x); + x = y; + } +} + +template <class Key, class Value, class KeyOfValue, class Compare, class Alloc> +void rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::erase(iterator first, + iterator last) { + if (first == begin() && last == end()) + clear(); + else + while (first != last) erase(first++); +} + +template <class Key, class Value, class KeyOfValue, class Compare, class Alloc> +void rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::erase(const Key* first, + const Key* last) { + while (first != last) erase(*first++); +} + +template <class Key, class Value, class KeyOfValue, class Compare, class Alloc> +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::find(const Key& k) { + link_type y = header; // Last node which is not less than k. + link_type x = root(); // Current node. + + while (x != 0) + if (!key_compare(key(x), k)) + y = x, x = left(x); + else + x = right(x); + + iterator j = iterator(y); + return (j == end() || key_compare(k, key(j.node))) ? end() : j; +} + +template <class Key, class Value, class KeyOfValue, class Compare, class Alloc> +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::const_iterator +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::find(const Key& k) const { + link_type y = header; /* Last node which is not less than k. */ + link_type x = root(); /* Current node. */ + + while (x != 0) { + if (!key_compare(key(x), k)) + y = x, x = left(x); + else + x = right(x); + } + const_iterator j = const_iterator(y); + return (j == end() || key_compare(k, key(j.node))) ? end() : j; +} + +template <class Key, class Value, class KeyOfValue, class Compare, class Alloc> +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::size_type +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::count(const Key& k) const { + pair<const_iterator, const_iterator> p = equal_range(k); + size_type n = 0; + distance(p.first, p.second, n); + return n; +} + +template <class Key, class Value, class KeyOfValue, class Compare, class Alloc> +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::lower_bound(const Key& k) { + link_type y = header; /* Last node which is not less than k. */ + link_type x = root(); /* Current node. */ + + while (x != 0) + if (!key_compare(key(x), k)) + y = x, x = left(x); + else + x = right(x); + + return iterator(y); +} + +template <class Key, class Value, class KeyOfValue, class Compare, class Alloc> +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::const_iterator +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::lower_bound(const Key& k) const { + link_type y = header; /* Last node which is not less than k. */ + link_type x = root(); /* Current node. */ + + while (x != 0) + if (!key_compare(key(x), k)) + y = x, x = left(x); + else + x = right(x); + + return const_iterator(y); +} + +template <class Key, class Value, class KeyOfValue, class Compare, class Alloc> +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::upper_bound(const Key& k) { + link_type y = header; /* Last node which is greater than k. */ + link_type x = root(); /* Current node. */ + + while (x != 0) + if (key_compare(k, key(x))) + y = x, x = left(x); + else + x = right(x); + + return iterator(y); +} + +template <class Key, class Value, class KeyOfValue, class Compare, class Alloc> +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::const_iterator +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::upper_bound(const Key& k) const { + link_type y = header; /* Last node which is greater than k. */ + link_type x = root(); /* Current node. */ + + while (x != 0) + if (key_compare(k, key(x))) + y = x, x = left(x); + else + x = right(x); + + return const_iterator(y); +} + +template <class Key, class Value, class KeyOfValue, class Compare, class Alloc> +inline pair<rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator, + rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator> +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::equal_range(const Key& k) { + return pair<iterator, iterator>(lower_bound(k), upper_bound(k)); +} + +template <class Key, class Value, class KeyOfValue, class Compare, class Alloc> +inline pair<rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::const_iterator, + rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::const_iterator> +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::equal_range(const Key& k) const { + return pair<const_iterator,const_iterator>(lower_bound(k), upper_bound(k)); +} + +inline int __black_count(__rb_tree_node_base* node, __rb_tree_node_base* root) +{ + if (node == 0) + return 0; + else { + int bc = node->color == __rb_tree_black ? 1 : 0; + if (node == root) + return bc; + else + return bc + __black_count(node->parent, root); + } +} + +template <class Key, class Value, class KeyOfValue, class Compare, class Alloc> +bool +rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::__rb_verify() const +{ + if (node_count == 0 || begin() == end()) + return node_count == 0 && begin() == end() && + header->left == header && header->right == header; + + int len = __black_count(leftmost(), root()); + for (const_iterator it = begin(); it != end(); ++it) { + link_type x = (link_type) it.node; + link_type L = left(x); + link_type R = right(x); + + if (x->color == __rb_tree_red) + if ((L && L->color == __rb_tree_red) || + (R && R->color == __rb_tree_red)) + return false; + + if (L && key_compare(key(x), key(L))) + return false; + if (R && key_compare(key(R), key(x))) + return false; + + if (!L && !R && __black_count(x, root()) != len) + return false; + } + + if (leftmost() != __rb_tree_node_base::minimum(root())) + return false; + if (rightmost() != __rb_tree_node_base::maximum(root())) + return false; + + return true; +} + +#endif /* __SGI_STL_TREE_H */ diff --git a/libstdc++/stl/type_traits.h b/libstdc++/stl/type_traits.h new file mode 100644 index 0000000..6ca0137 --- /dev/null +++ b/libstdc++/stl/type_traits.h @@ -0,0 +1,227 @@ +/* + * + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#ifndef __TYPE_TRAITS_H +#define __TYPE_TRAITS_H + +#include <stl_config.h> + +/* +This header file provides a framework for allowing compile time dispatch +based on type attributes. This is useful when writing template code. +For example, when making a copy of an array of an unknown type, it helps +to know if the type has a trivial copy constructor or not, to help decide +if a memcpy can be used. + +The class template __type_traits provides a series of typedefs each of +which is either __true_type or __false_type. The argument to +__type_traits can be any type. The typedefs within this template will +attain their correct values by one of these means: + 1. The general instantiation contain conservative values which work + for all types. + 2. Specializations may be declared to make distinctions between types. + 3. Some compilers (such as the Silicon Graphics N32 and N64 compilers) + will automatically provide the appropriate specializations for all + types. + +EXAMPLE: + +//Copy an array of elements which have non-trivial copy constructors +template <class T> void copy(T* source,T* destination,int n,__false_type); +//Copy an array of elements which have trivial copy constructors. Use memcpy. +template <class T> void copy(T* source,T* destination,int n,__true_type); + +//Copy an array of any type by using the most efficient copy mechanism +template <class T> inline void copy(T* source,T* destination,int n) { + copy(source,destination,n,__type_traits<T>::has_trivial_copy_constructor()); +} +*/ + + +struct __true_type { +}; + +struct __false_type { +}; + +template <class type> +struct __type_traits { + typedef __true_type this_dummy_member_must_be_first; + /* Do not remove this member. It informs a compiler which + automatically specializes __type_traits that this + __type_traits template is special. It just makes sure that + things work if an implementation is using a template + called __type_traits for something unrelated. */ + + /* The following restrictions should be observed for the sake of + compilers which automatically produce type specific specializations + of this class: + - You may reorder the members below if you wish + - You may remove any of the members below if you wish + - You must not rename members without making the corresponding + name change in the compiler + - Members you add will be treated like regular members unless + you add the appropriate support in the compiler. */ + + + typedef __false_type has_trivial_default_constructor; + typedef __false_type has_trivial_copy_constructor; + typedef __false_type has_trivial_assignment_operator; + typedef __false_type has_trivial_destructor; + typedef __false_type is_POD_type; +}; + + + +// Provide some specializations. This is harmless for compilers that +// have built-in __types_traits support, and essential for compilers +// that don't. + +struct __type_traits<char> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +struct __type_traits<signed char> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +struct __type_traits<unsigned char> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +struct __type_traits<short> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +struct __type_traits<unsigned short> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +struct __type_traits<int> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +struct __type_traits<unsigned int> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +struct __type_traits<long> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +struct __type_traits<unsigned long> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +struct __type_traits<float> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +struct __type_traits<double> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +struct __type_traits<long double> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION + +template <class T> +struct __type_traits<T*> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +struct __type_traits<char*> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +struct __type_traits<signed char*> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +struct __type_traits<unsigned char*> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + + +#endif /* __TYPE_TRAITS_H */ diff --git a/libstdc++/stl/vector.h b/libstdc++/stl/vector.h new file mode 100644 index 0000000..bb6a404 --- /dev/null +++ b/libstdc++/stl/vector.h @@ -0,0 +1,544 @@ +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#ifndef __SGI_STL_VECTOR_H +#define __SGI_STL_VECTOR_H + +#include <stddef.h> +#include <algobase.h> +#include <alloc.h> + +template <class T, class Alloc = alloc> +class vector { +public: + typedef T value_type; + typedef value_type* pointer; + typedef value_type* iterator; + typedef const value_type* const_iterator; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef reverse_iterator<const_iterator, value_type, const_reference, + difference_type> const_reverse_iterator; + typedef reverse_iterator<iterator, value_type, reference, difference_type> + reverse_iterator; +protected: + typedef simple_alloc<value_type, Alloc> data_allocator; + iterator start; + iterator finish; + iterator end_of_storage; + void insert_aux(iterator position, const T& x); + void deallocate() { + if (start) data_allocator::deallocate(start, end_of_storage - start); + } +public: + iterator begin() { return start; } + const_iterator begin() const { return start; } + iterator end() { return finish; } + const_iterator end() const { return finish; } + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + size_type size() const { return size_type(end() - begin()); } + size_type max_size() const { return size_type(-1); } + size_type capacity() const { return size_type(end_of_storage - begin()); } + bool empty() const { return begin() == end(); } + reference operator[](size_type n) { return *(begin() + n); } + const_reference operator[](size_type n) const { return *(begin() + n); } + vector() : start(0), finish(0), end_of_storage(0) {} + vector(size_type n, const T& value) { + start = allocate_and_fill(n, value); + finish = start + n; + end_of_storage = finish; + } + explicit vector(size_type n) { + start = allocate_and_fill(n, T()); + finish = start + n; + end_of_storage = finish; + } + vector(const vector<T, Alloc>& x) { + start = allocate_and_copy(x.end() - x.begin(), x.begin(), x.end()); + finish = start + (x.end() - x.begin()); + end_of_storage = finish; + } +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + vector(InputIterator first, InputIterator last) : + start(0), finish(0), end_of_storage(0) { + range_initialize(first, last, iterator_category(first)); + } +#else /* __STL_MEMBER_TEMPLATES */ + vector(const_iterator first, const_iterator last) { + size_type n = 0; + distance(first, last, n); + start = allocate_and_copy(n, first, last); + finish = start + n; + end_of_storage = finish; + } +#endif /* __STL_MEMBER_TEMPLATES */ + ~vector() { + destroy(start, finish); + deallocate(); + } + vector<T, Alloc>& operator=(const vector<T, Alloc>& x); + void reserve(size_type n) { + if (capacity() < n) { + const size_type old_size = size(); + const iterator tmp = allocate_and_copy(n, start, finish); + destroy(start, finish); + deallocate(); + start = tmp; + finish = tmp + old_size; + end_of_storage = start + n; + } + } + reference front() { return *begin(); } + const_reference front() const { return *begin(); } + reference back() { return *(end() - 1); } + const_reference back() const { return *(end() - 1); } + void push_back(const T& x) { + if (finish != end_of_storage) { + construct(finish, x); + ++finish; + } else + insert_aux(end(), x); + } + void swap(vector<T, Alloc>& x) { + ::swap(start, x.start); + ::swap(finish, x.finish); + ::swap(end_of_storage, x.end_of_storage); + } + iterator insert(iterator position, const T& x) { + size_type n = position - begin(); + if (finish != end_of_storage && position == end()) { + construct(finish, x); + ++finish; + } else + insert_aux(position, x); + return begin() + n; + } + iterator insert(iterator position) { return insert(position, T()); } +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + void insert(iterator position, InputIterator first, InputIterator last) { + range_insert(position, first, last, iterator_category(first)); + } +#else /* __STL_MEMBER_TEMPLATES */ + void insert(iterator position, + const_iterator first, const_iterator last); +#endif /* __STL_MEMBER_TEMPLATES */ + void insert (iterator position, size_type n, const T& x); + void pop_back() { + --finish; + destroy(finish); + } + void erase(iterator position) { + if (position + 1 != end()) + copy(position + 1, finish, position); + --finish; + destroy(finish); + } + void erase(iterator first, iterator last) { + iterator i = copy(last, finish, first); + destroy(i, finish); + finish = finish - (last - first); + } + void resize(size_type new_size, const T& x) { + if (new_size < size()) + erase(begin() + new_size, end()); + else + insert(end(), new_size - size(), x); + } + void resize(size_type new_size) { resize(new_size, T()); } + void clear() { erase(begin(), end()); } + +protected: + iterator allocate_and_fill(size_type n, const T& x) { + iterator result = data_allocator::allocate(n); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + uninitialized_fill_n(result, n, x); + return result; +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + data_allocator::deallocate(result, n); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } + +#ifdef __STL_MEMBER_TEMPLATES + template <class ForwardIterator> + iterator allocate_and_copy(size_type n, + ForwardIterator first, ForwardIterator last) { + iterator result = data_allocator::allocate(n); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + uninitialized_copy(first, last, result); + return result; +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + data_allocator::deallocate(result, n); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } +#else /* __STL_MEMBER_TEMPLATES */ + iterator allocate_and_copy(size_type n, + const_iterator first, const_iterator last) { + iterator result = data_allocator::allocate(n); +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + uninitialized_copy(first, last, result); + return result; +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + data_allocator::deallocate(result, n); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + } +#endif /* __STL_MEMBER_TEMPLATES */ + + +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + void range_initialize(InputIterator first, InputIterator last, + input_iterator_tag) { + for ( ; first != last; ++first) + push_back(*first); + } + + // This function is only called by the constructor. We have to worry + // about resource leaks, but not about maintaining invariants. + template <class ForwardIterator> + void range_initialize(ForwardIterator first, ForwardIterator last, + forward_iterator_tag) { + size_type n = 0; + distance(first, last, n); + start = allocate_and_copy(n, first, last); + finish = start + n; + end_of_storage = finish; + } + + template <class BidirectionalIterator> + void range_initialize(BidirectionalIterator first, + BidirectionalIterator last, + bidirectional_iterator_tag) { + range_initialize(first, last, forward_iterator_tag()); + } + + template <class RandomAccessIterator> + void range_initialize(RandomAccessIterator first, + RandomAccessIterator last, + random_access_iterator_tag) { + range_initialize(first, last, forward_iterator_tag()); + } + + template <class InputIterator> + void range_insert(iterator pos, + InputIterator first, InputIterator last, + input_iterator_tag); + + template <class ForwardIterator> + void range_insert(iterator pos, + ForwardIterator first, ForwardIterator last, + forward_iterator_tag); + + template <class BidirectionalIterator> + void range_insert(iterator pos, + BidirectionalIterator first, BidirectionalIterator last, + bidirectional_iterator_tag) { + range_insert(pos, first, last, forward_iterator_tag()); + } + + template <class RandomAccessIterator> + void range_insert(iterator pos, + RandomAccessIterator first, RandomAccessIterator last, + random_access_iterator_tag) { + range_insert(pos, first, last, forward_iterator_tag()); + } +#endif /* __STL_MEMBER_TEMPLATES */ +}; + +template <class T, class Alloc> +inline bool operator==(const vector<T, Alloc>& x, const vector<T, Alloc>& y) { + return x.size() == y.size() && equal(x.begin(), x.end(), y.begin()); +} + +template <class T, class Alloc> +inline bool operator<(const vector<T, Alloc>& x, const vector<T, Alloc>& y) { + return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); +} + + + +template <class T, class Alloc> +vector<T, Alloc>& vector<T, Alloc>::operator=(const vector<T, Alloc>& x) { + if (&x != this) { + if (x.size() > capacity()) { + const iterator tmp = allocate_and_copy(x.end() - x.begin(), + x.begin(), x.end()); + destroy(start, finish); + deallocate(); + start = tmp; + end_of_storage = start + (x.end() - x.begin()); + } + else if (size() >= x.size()) { + iterator i = copy(x.begin(), x.end(), begin()); + destroy(i, finish); + } + else { + copy(x.begin(), x.begin() + size(), start); + uninitialized_copy(x.begin() + size(), x.end(), finish); + } + finish = start + x.size(); + } + return *this; +} + +template <class T, class Alloc> +void vector<T, Alloc>::insert_aux(iterator position, const T& x) { + if (finish != end_of_storage) { + construct(finish, *(finish - 1)); + ++finish; + T x_copy = x; + copy_backward(position, finish - 2, finish - 1); + *position = x_copy; + } + else { + const size_type old_size = size(); + const size_type len = old_size != 0 ? 2 * old_size : 1; + const iterator new_start = data_allocator::allocate(len); + iterator new_finish = new_start; +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + new_finish = uninitialized_copy(start, position, new_start); + construct(new_finish, x); + ++new_finish; + new_finish = uninitialized_copy(position, finish, new_finish); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy(new_start, new_finish); + data_allocator::deallocate(new_start, len); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + destroy(begin(), end()); + deallocate(); + start = new_start; + finish = new_finish; + end_of_storage = new_start + len; + } +} + +template <class T, class Alloc> +void vector<T, Alloc>::insert(iterator position, size_type n, const T& x) { + if (n != 0) { + if (size_type (end_of_storage - finish) >= n) { + T x_copy = x; + const size_type elems_after = finish - position; + const iterator old_finish = finish; + if (elems_after > n) { + uninitialized_copy(finish - n, finish, finish); + finish += n; + copy_backward(position, old_finish - n, old_finish); + fill(position, position + n, x_copy); + } + else { + uninitialized_fill_n(finish, n - elems_after, x_copy); + finish += n - elems_after; + uninitialized_copy(position, old_finish, finish); + finish += elems_after; + fill(position, old_finish, x_copy); + } + } + else { + const size_type old_size = size(); + const size_type len = old_size + max(old_size, n); + const iterator new_start = data_allocator::allocate(len); + iterator new_finish = new_start; +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + new_finish = uninitialized_copy(start, position, new_start); + new_finish = uninitialized_fill_n(new_finish, n, x); + new_finish = uninitialized_copy(position, finish, new_finish); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy(new_start, new_finish); + data_allocator::deallocate(new_start, len); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + destroy(start, finish); + deallocate(); + start = new_start; + finish = new_finish; + end_of_storage = new_start + len; + } + } +} + +#ifdef __STL_MEMBER_TEMPLATES + +template <class T, class Alloc> template <class InputIterator> +void vector<T, Alloc>::range_insert(iterator pos, + InputIterator first, InputIterator last, + input_iterator_tag) { + for ( ; first != last; ++first) { + pos = insert(pos, *first); + ++pos; + } +} + +template <class T, class Alloc> template <class ForwardIterator> +void vector<T, Alloc>::range_insert(iterator position, + ForwardIterator first, + ForwardIterator last, + forward_iterator_tag) { + if (first != last) { + size_type n = 0; + distance(first, last, n); + if (size_type (end_of_storage - finish) >= n) { + const size_type elems_after = finish - position; + const iterator old_finish = finish; + if (elems_after > n) { + uninitialized_copy(finish - n, finish, finish); + finish += n; + copy_backward(position, old_finish - n, old_finish); + copy(first, last, position); + } + else { + ForwardIterator mid = first; + advance(mid, elems_after); + uninitialized_copy(mid, last, finish); + finish += n - elems_after; + uninitialized_copy(position, old_finish, finish); + finish += elems_after; + copy(first, mid, position); + } + } + else { + const size_type old_size = size(); + const size_type len = old_size + max(old_size, n); + const iterator new_start = data_allocator::allocate(len); + iterator new_finish = new_start; +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + new_finish = uninitialized_copy(start, position, new_start); + new_finish = uninitialized_copy(first, last, new_finish); + new_finish = uninitialized_copy(position, finish, new_finish); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy(new_start, new_finish); + data_allocator::deallocate(new_start, len); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + destroy(start, finish); + deallocate(); + start = new_start; + finish = new_finish; + end_of_storage = new_start + len; + } + } +} + +#else /* __STL_MEMBER_TEMPLATES */ + +template <class T, class Alloc> +void vector<T, Alloc>::insert(iterator position, + const_iterator first, + const_iterator last) { + if (first != last) { + size_type n = 0; + distance(first, last, n); + if (end_of_storage - finish >= n) { + const size_type elems_after = finish - position; + const iterator old_finish = finish; + if (elems_after > n) { + uninitialized_copy(finish - n, finish, finish); + finish += n; + copy_backward(position, old_finish - n, old_finish); + copy(first, last, position); + } + else { + uninitialized_copy(first + elems_after, last, finish); + finish += n - elems_after; + uninitialized_copy(position, old_finish, finish); + finish += elems_after; + copy(first, first + elems_after, position); + } + } + else { + const size_type old_size = size(); + const size_type len = old_size + max(old_size, n); + const iterator new_start = data_allocator::allocate(len); + iterator new_finish = new_start; +# ifdef __STL_USE_EXCEPTIONS + try { +# endif /* __STL_USE_EXCEPTIONS */ + new_finish = uninitialized_copy(start, position, new_start); + new_finish = uninitialized_copy(first, last, new_finish); + new_finish = uninitialized_copy(position, finish, new_finish); +# ifdef __STL_USE_EXCEPTIONS + } + catch(...) { + destroy(new_start, new_finish); + data_allocator::deallocate(new_start, len); + throw; + } +# endif /* __STL_USE_EXCEPTIONS */ + destroy(start, finish); + deallocate(); + start = new_start; + finish = new_finish; + end_of_storage = new_start + len; + } + } +} + +#endif /* __STL_MEMBER_TEMPLATES */ + +#endif /* __SGI_STL_VECTOR_H */ |