diff options
Diffstat (limited to 'libstdc++/stl')
77 files changed, 17947 insertions, 15363 deletions
diff --git a/libstdc++/stl/ChangeLog b/libstdc++/stl/ChangeLog index ca1c01a626f..7d0c62ab462 100644 --- a/libstdc++/stl/ChangeLog +++ b/libstdc++/stl/ChangeLog @@ -1,3 +1,21 @@ +Sun Nov 2 12:14:56 1997 Jason Merrill <jason@yorick.cygnus.com> + + * algo.h, algobase.h, alloc.h, bvector.h, defalloc.h, deque.h, + function.h, hash_map.h, hash_set.h, hashtable.h, heap.h, iterator.h, + list.h, map.h, multimap.h, multiset.h, pair.h, pthread_alloc.h, + rope.h, ropeimpl.h, set.h, slist.h, stack.h, stl_config.h, tempbuf.h, + tree.h, type_traits.h, vector.h: Update to October 27 SGI snapshot. + * algorithm, deque, functional, hash_map, hash_set, iterator, list, + map, memory, numeric, pthread_alloc, queue, rope, set, slist, stack, + stl_algo.h, stl_algobase.h, stl_alloc.h, stl_bvector.h, + stl_construct.h, stl_deque.h, stl_function.h, stl_hash_fun.h, + stl_hash_map.h, stl_hash_set.h, stl_hashtable.h, stl_heap.h, + stl_iterator.h, stl_list.h, stl_map.h, stl_multimap.h, stl_multiset.h, + stl_numeric.h, stl_pair.h, stl_queue.h, stl_raw_storage_iter.h, + stl_relops.h, stl_rope.h, stl_set.h, stl_slist.h, stl_stack.h, + stl_tempbuf.h, stl_tree.h, stl_uninitialized.h, stl_vector.h, + utility, vector: New files in October 27 SGI snapshot. + Fri Oct 17 19:07:42 1997 Jason Merrill <jason@yorick.cygnus.com> * tree.h, vector.h: Fix accidental divergence from SGI release. diff --git a/libstdc++/stl/algo.h b/libstdc++/stl/algo.h index 2f142898d8b..1707868c7c4 100644 --- a/libstdc++/stl/algo.h +++ b/libstdc++/stl/algo.h @@ -12,7 +12,7 @@ * purpose. It is provided "as is" without express or implied warranty. * * - * Copyright (c) 1996 + * Copyright (c) 1996,1997 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, modify, distribute and sell this software @@ -27,2851 +27,88 @@ #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 ForwardIterator, class Integer, class T> -ForwardIterator search_n(ForwardIterator first, ForwardIterator last, - Integer count, const T& value) { - if (count <= 0) - return first; - else { - first = find(first, last, value); - while (first != last) { - Integer n = count - 1; - ForwardIterator i = first; - ++i; - while (i != last && n != 0 && *i == value) { - ++i; - --n; - } - if (n == 0) - return first; - else - first = find(i, last, value); - } - return last; - } -} - -template <class ForwardIterator, class Integer, class T, class BinaryPredicate> -ForwardIterator search_n(ForwardIterator first, ForwardIterator last, - Integer count, const T& value, - BinaryPredicate binary_pred) { - if (count <= 0) - return first; - else { - while (first != last) { - if (binary_pred(*first, value)) break; - ++first; - } - while (first != last) { - Integer n = count - 1; - ForwardIterator i = first; - ++i; - while (i != last && n != 0 && binary_pred(*i, value)) { - ++i; - --n; - } - if (n == 0) - return first; - else { - while (i != last) { - if (binary_pred(*i, value)) break; - ++i; - } - first = i; - } - } - return last; - } -} - -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 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 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 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 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 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 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); -} - -template <class InputIterator, class ForwardIterator> -InputIterator find_first_of(InputIterator first1, InputIterator last1, - ForwardIterator first2, ForwardIterator last2) -{ - for ( ; first1 != last1; ++first1) - for (ForwardIterator iter = first2; iter != last2; ++iter) - if (*first1 == *iter) - return first1; - return last1; -} - -template <class InputIterator, class ForwardIterator, class BinaryPredicate> -InputIterator find_first_of(InputIterator first1, InputIterator last1, - ForwardIterator first2, ForwardIterator last2, - BinaryPredicate comp) -{ - for ( ; first1 != last1; ++first1) - for (ForwardIterator iter = first2; iter != last2; ++iter) - if (comp(*first1, *iter)) - return first1; - return last1; -} - - -// Search [first2, last2) as a subsequence in [first1, last1). - -// find_end for forward iterators. -template <class ForwardIterator1, class ForwardIterator2> -ForwardIterator1 __find_end(ForwardIterator1 first1, ForwardIterator1 last1, - ForwardIterator2 first2, ForwardIterator2 last2, - forward_iterator_tag, forward_iterator_tag) -{ - if (first2 == last2) - return last1; - else { - ForwardIterator1 result = last1; - while (1) { - ForwardIterator1 new_result = search(first1, last1, first2, last2); - if (new_result == last1) - return result; - else { - result = new_result; - first1 = new_result; - ++first1; - } - } - } -} - -template <class ForwardIterator1, class ForwardIterator2, - class BinaryPredicate> -ForwardIterator1 __find_end(ForwardIterator1 first1, ForwardIterator1 last1, - ForwardIterator2 first2, ForwardIterator2 last2, - forward_iterator_tag, forward_iterator_tag, - BinaryPredicate comp) -{ - if (first2 == last2) - return last1; - else { - ForwardIterator1 result = last1; - while (1) { - ForwardIterator1 new_result = search(first1, last1, first2, last2, comp); - if (new_result == last1) - return result; - else { - result = new_result; - first1 = new_result; - ++first1; - } - } - } -} - -// find_end for bidirectional iterators. Requires partial specialization. -#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION - -template <class BidirectionalIterator1, class BidirectionalIterator2> -BidirectionalIterator1 -__find_end(BidirectionalIterator1 first1, BidirectionalIterator1 last1, - BidirectionalIterator2 first2, BidirectionalIterator2 last2, - bidirectional_iterator_tag, bidirectional_iterator_tag) -{ - typedef reverse_iterator<BidirectionalIterator1> reviter1; - typedef reverse_iterator<BidirectionalIterator2> reviter2; - - reviter1 rlast1(first1); - reviter2 rlast2(first2); - reviter1 rresult = search(reviter1(last1), rlast1, reviter2(last2), rlast2); - - if (rresult == rlast1) - return last1; - else { - BidirectionalIterator1 result = rresult.base(); - advance(result, -distance(first2, last2)); - return result; - } -} - -template <class BidirectionalIterator1, class BidirectionalIterator2, - class BinaryPredicate> -BidirectionalIterator1 -__find_end(BidirectionalIterator1 first1, BidirectionalIterator1 last1, - BidirectionalIterator2 first2, BidirectionalIterator2 last2, - bidirectional_iterator_tag, bidirectional_iterator_tag, - BinaryPredicate comp) -{ - typedef reverse_iterator<BidirectionalIterator1> reviter1; - typedef reverse_iterator<BidirectionalIterator2> reviter2; - - reviter1 rlast1(first1); - reviter2 rlast2(first2); - reviter1 rresult = search(reviter1(last1), rlast1, reviter2(last2), rlast2, - comp); - - if (rresult == rlast1) - return last1; - else { - BidirectionalIterator1 result = rresult.base(); - advance(result, -distance(first2, last2)); - return result; - } -} -#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ - -// Dispatching functions. - -template <class ForwardIterator, class BidirectionalIterator> -inline ForwardIterator -__find_end(ForwardIterator first1, ForwardIterator last1, - BidirectionalIterator first2, BidirectionalIterator last2, - forward_iterator_tag, bidirectional_iterator_tag) -{ - return __find_end(first1, last1, first2, last2, - forward_iterator_tag(), forward_iterator_tag()); -} - -template <class BidirectionalIterator, class ForwardIterator> -inline BidirectionalIterator -__find_end(BidirectionalIterator first1, BidirectionalIterator last1, - ForwardIterator first2, ForwardIterator last2, - bidirectional_iterator_tag, forward_iterator_tag) -{ - return __find_end(first1, last1, first2, last2, - forward_iterator_tag(), forward_iterator_tag()); -} - -template <class ForwardIterator, class BidirectionalIterator, - class BinaryPredicate> -inline ForwardIterator -__find_end(ForwardIterator first1, ForwardIterator last1, - BidirectionalIterator first2, BidirectionalIterator last2, - forward_iterator_tag, bidirectional_iterator_tag, - BinaryPredicate comp) -{ - return __find_end(first1, last1, first2, last2, - forward_iterator_tag(), forward_iterator_tag(), - comp); - -} - -template <class BidirectionalIterator, class ForwardIterator, - class BinaryPredicate> -inline BidirectionalIterator -__find_end(BidirectionalIterator first1, BidirectionalIterator last1, - ForwardIterator first2, ForwardIterator last2, - bidirectional_iterator_tag, forward_iterator_tag, - BinaryPredicate comp) -{ - return __find_end(first1, last1, first2, last2, - forward_iterator_tag(), forward_iterator_tag(), - comp); -} - -template <class ForwardIterator1, class ForwardIterator2> -inline ForwardIterator1 -find_end(ForwardIterator1 first1, ForwardIterator1 last1, - ForwardIterator2 first2, ForwardIterator2 last2) -{ -#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION - return __find_end(first1, last1, first2, last2, - iterator_traits<ForwardIterator1>::iterator_category(), - iterator_traits<ForwardIterator2>::iterator_category()); -#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ - return __find_end(first1, last1, first2, last2, - forward_iterator_tag(), forward_iterator_tag()); -#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ -} - -template <class ForwardIterator1, class ForwardIterator2, - class BinaryPredicate> -inline ForwardIterator1 -find_end(ForwardIterator1 first1, ForwardIterator1 last1, - ForwardIterator2 first2, ForwardIterator2 last2, - BinaryPredicate comp) -{ -#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION - return __find_end(first1, last1, first2, last2, - iterator_traits<ForwardIterator1>::iterator_category(), - iterator_traits<ForwardIterator2>::iterator_category(), - comp); -#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ - return __find_end(first1, last1, first2, last2, - forward_iterator_tag(), forward_iterator_tag(), - comp); -#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ -} - -// 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 & 1) == 0) { - n >>= 1; - x = op(x, x); - } - - T result = x; - n >>= 1; - while (n != 0) { - x = op(x, x); - if ((n & 1) != 0) - result = op(result, x); - n >>= 1; - } - 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 +#include <stl_algo.h> +#include <stl_numeric.h> + +#ifdef __STL_USE_NAMESPACES + +// Names from <stl_algo.h> +using __STD::for_each; +using __STD::find; +using __STD::find_if; +using __STD::adjacent_find; +using __STD::count; +using __STD::count_if; +using __STD::search; +using __STD::search_n; +using __STD::swap_ranges; +using __STD::transform; +using __STD::replace; +using __STD::replace_if; +using __STD::replace_copy; +using __STD::replace_copy_if; +using __STD::generate; +using __STD::generate_n; +using __STD::remove; +using __STD::remove_if; +using __STD::remove_copy; +using __STD::remove_copy_if; +using __STD::unique; +using __STD::unique_copy; +using __STD::reverse; +using __STD::reverse_copy; +using __STD::rotate; +using __STD::rotate_copy; +using __STD::random_shuffle; +using __STD::random_sample; +using __STD::random_sample_n; +using __STD::partition; +using __STD::stable_partition; +using __STD::sort; +using __STD::stable_sort; +using __STD::partial_sort; +using __STD::partial_sort_copy; +using __STD::nth_element; +using __STD::lower_bound; +using __STD::upper_bound; +using __STD::equal_range; +using __STD::binary_search; +using __STD::merge; +using __STD::inplace_merge; +using __STD::includes; +using __STD::set_union; +using __STD::set_intersection; +using __STD::set_difference; +using __STD::set_symmetric_difference; +using __STD::min_element; +using __STD::max_element; +using __STD::next_permutation; +using __STD::prev_permutation; +using __STD::find_first_of; +using __STD::find_end; +using __STD::is_sorted; +using __STD::is_heap; + +// Names from stl_heap.h +using __STD::push_heap; +using __STD::pop_heap; +using __STD::make_heap; +using __STD::sort_heap; + +// Names from <stl_numeric.h> +using __STD::accumulate; +using __STD::inner_product; +using __STD::partial_sum; +using __STD::adjacent_difference; +using __STD::power; +using __STD::iota; + +#endif /* __STL_USE_NAMESPACES */ #endif /* __SGI_STL_ALGO_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/algobase.h b/libstdc++/stl/algobase.h index eccf465d52c..f35e7af4a97 100644 --- a/libstdc++/stl/algobase.h +++ b/libstdc++/stl/algobase.h @@ -11,8 +11,7 @@ * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. * - * - * Copyright (c) 1996 + * Copyright (c) 1996,1997 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, modify, distribute and sell this software @@ -24,743 +23,49 @@ * purpose. It is provided "as is" without express or implied warranty. */ -#ifndef _SGI_STL_ALGOBASE_H -#define _SGI_STL_ALGOBASE_H +#ifndef __SGI_STL_ALGOBASE_H +#define __SGI_STL_ALGOBASE_H -#include <string.h> -#include <limits.h> -#include <function.h> +#ifndef __SGI_STL_PAIR_H #include <pair.h> +#endif +#ifndef __SGI_STL_ITERATOR_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 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 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; -} - -#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) -#pragma set woff 1183 +#ifndef __SGI_STL_INTERNAL_ALGOBASE_H +#include <stl_algobase.h> #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 +#ifndef __SGI_STL_INTERNAL_UNINITIALIZED_H +#include <stl_uninitialized.h> #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 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 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 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 */ +#ifdef __STL_USE_NAMESPACES + +// Names from stl_algobase.h +using __STD::iter_swap; +using __STD::swap; +using __STD::min; +using __STD::max; +using __STD::copy; +using __STD::copy_backward; +using __STD::copy_n; +using __STD::fill; +using __STD::fill_n; +using __STD::mismatch; +using __STD::equal; +using __STD::lexicographical_compare; +using __STD::lexicographical_compare_3way; + +// Names from stl_uninitialized.h +using __STD::uninitialized_copy; +using __STD::uninitialized_copy_n; +using __STD::uninitialized_fill; +using __STD::uninitialized_fill_n; + +#endif /* __STL_USE_NAMESPACES */ + +#endif /* __SGI_STL_ALGOBASE_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/algorithm b/libstdc++/stl/algorithm new file mode 100644 index 00000000000..515e9bd25da --- /dev/null +++ b/libstdc++/stl/algorithm @@ -0,0 +1,39 @@ +/* + * + * 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,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_ALGORITHM +#define __SGI_STL_ALGORITHM + +#include <stl_algobase.h> +#include <stl_construct.h> +#include <stl_tempbuf.h> +#include <stl_algo.h> + +#endif /* __SGI_STL_ALGORITHM */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/alloc.h b/libstdc++/stl/alloc.h index 8831976c614..7cc96100605 100644 --- a/libstdc++/stl/alloc.h +++ b/libstdc++/stl/alloc.h @@ -11,674 +11,34 @@ * purpose. It is provided "as is" without express or implied warranty. */ -#ifndef __ALLOC_H -#define __ALLOC_H +#ifndef __SGI_STL_ALLOC_H +#define __SGI_STL_ALLOC_H +#ifndef __STL_CONFIG_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> -#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 +#ifndef __SGI_STL_INTERNAL_ALLOC_H +#include <stl_alloc.h> #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. - - extern int __us_rsthread_malloc; - // The above is copied from malloc.h. Including <malloc.h> - // would be cleaner but fails with certain levels of standard - // conformance. -# 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 +#ifdef __STL_USE_NAMESPACES -// Malloc-based allocator. Typically slower than default alloc below. -// Typically thread-safe and more storage efficient. +using __STD::__malloc_alloc_template; +using __STD::malloc_alloc; +using __STD::simple_alloc; +using __STD::debug_alloc; +using __STD::__default_alloc_template; +using __STD::alloc; +using __STD::single_client_alloc; #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; +using __STD::__malloc_alloc_oom_handler; +#endif /* __STL_STATIC_TEMPLATE_MEMBER_BUG */ -# else +#endif /* __STL_USE_NAMESPACES */ -// 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 > (size_t) __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. -# ifndef _NOTHREADS - /*REFERENCED*/ - lock lock_instance; -# endif - 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 > (size_t) __MAX_BYTES) { - malloc_alloc::deallocate(p, n); - return; - } - my_free_list = free_list + FREELIST_INDEX(n); - // acquire lock -# ifndef _NOTHREADS - /*REFERENCED*/ - lock lock_instance; -# endif /* _NOTHREADS */ - 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. - } - } - end_free = 0; // In case of exception. - 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 > (size_t) __MAX_BYTES && new_sz > (size_t) __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 - -#undef __PRIVATE +#endif /* __SGI_STL_ALLOC_H */ -#endif /* __ALLOC_H */ +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/bvector.h b/libstdc++/stl/bvector.h index 71b49173c40..03a3fb1c7f2 100644 --- a/libstdc++/stl/bvector.h +++ b/libstdc++/stl/bvector.h @@ -24,541 +24,28 @@ * 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> +#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION +#include <vector.h> +#else #include <algobase.h> #include <alloc.h> +#endif +#include <stl_bvector.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; - typedef bit_reference* pointer; - 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; - typedef const bool* pointer; - 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); - } - }; - -#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION - typedef reverse_iterator<const_iterator> const_reverse_iterator; - typedef reverse_iterator<iterator> reverse_iterator; -#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ - 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; -#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ - -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); - } +#ifdef __STL_USE_NAMESPACES - template <class InputIterator> - void insert_range(iterator pos, - InputIterator first, InputIterator last, - input_iterator_tag) { - for ( ; first != last; ++first) { - pos = insert(pos, *first); - ++pos; - } - } +using __STD::bit_vector; - 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); - } - } - } +#endif /* __STL_USE_NAMESPACES */ -#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()); -} +#endif /* __SGI_STL_BVECTOR_H */ -inline void swap(bit_vector::reference x, bit_vector::reference y) { - bool tmp = x; - x = y; - y = tmp; -} +// Local Variables: +// mode:C++ +// End: -#undef __WORD_BIT -#endif /* __SGI_STL_BVECTOR_H */ diff --git a/libstdc++/stl/defalloc.h b/libstdc++/stl/defalloc.h index e7d24d38c84..49690f8d6e0 100644 --- a/libstdc++/stl/defalloc.h +++ b/libstdc++/stl/defalloc.h @@ -12,16 +12,15 @@ * 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. -// + +// Inclusion of this file is DEPRECATED. This is the original HP +// default allocator. It is provided only for backward compatibility. +// +// 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 diff --git a/libstdc++/stl/deque b/libstdc++/stl/deque new file mode 100644 index 00000000000..61654acad5b --- /dev/null +++ b/libstdc++/stl/deque @@ -0,0 +1,40 @@ +/* + * + * 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 +#define __SGI_STL_DEQUE + +#include <stl_algobase.h> +#include <stl_alloc.h> +#include <stl_construct.h> +#include <stl_uninitialized.h> +#include <stl_deque.h> + +#endif /* __SGI_STL_DEQUE */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/deque.h b/libstdc++/stl/deque.h index e202a117398..ede38b1ceba 100644 --- a/libstdc++/stl/deque.h +++ b/libstdc++/stl/deque.h @@ -27,1413 +27,16 @@ #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> +#include <stl_deque.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, class Ptr, size_t BufSiz> -struct __deque_iterator { - typedef __deque_iterator<T, T&, T*, BufSiz> iterator; - typedef __deque_iterator<T, const 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, class Ptr> -struct __deque_iterator { - typedef __deque_iterator<T, T&, T*> iterator; - typedef __deque_iterator<T, const 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 Ptr pointer; - typedef Ref reference; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef T** map_pointer; - - typedef __deque_iterator self; - - T* cur; - T* first; - T* last; - map_pointer node; - - __deque_iterator(T* 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) {} - - reference operator*() const { return *cur; } -#ifndef __SGI_STL_NO_ARROW_OPERATOR - pointer operator->() const { return &(operator*()); } -#endif /* __SGI_STL_NO_ARROW_OPERATOR */ - - 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; - } - - reference 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_CLASS_PARTIAL_SPECIALIZATION - -#ifndef __STL_NON_TYPE_TMPL_PARAM_BUG - -template <class T, class Ref, class Ptr, size_t BufSiz> -inline random_access_iterator_tag -iterator_category(const __deque_iterator<T, Ref, Ptr, BufSiz>&) { - return random_access_iterator_tag(); -} - -template <class T, class Ref, class Ptr, size_t BufSiz> -inline T* value_type(const __deque_iterator<T, Ref, Ptr, BufSiz>&) { - return 0; -} - -template <class T, class Ref, class Ptr, size_t BufSiz> -inline ptrdiff_t* distance_type(const __deque_iterator<T, Ref, Ptr, BufSiz>&) { - return 0; -} - -#else /* __STL_NON_TYPE_TMPL_PARAM_BUG */ - -template <class T, class Ref, class Ptr> -inline random_access_iterator_tag -iterator_category(const __deque_iterator<T, Ref, Ptr>&) { - return random_access_iterator_tag(); -} - -template <class T, class Ref, class Ptr> -inline T* value_type(const __deque_iterator<T, Ref, Ptr>&) { return 0; } - -template <class T, class Ref, class Ptr> -inline ptrdiff_t* distance_type(const __deque_iterator<T, Ref, Ptr>&) { - return 0; -} - -#endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */ - -#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ - -// 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<T, T&, T*, BufSiz> iterator; - typedef __deque_iterator<T, const T&, const T&, BufSiz> const_iterator; -#else /* __STL_NON_TYPE_TMPL_PARAM_BUG */ - typedef __deque_iterator<T, T&, T*> iterator; - typedef __deque_iterator<T, const T&, const T*> const_iterator; -#endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */ - -#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION - typedef reverse_iterator<const_iterator> const_reverse_iterator; - typedef reverse_iterator<iterator> reverse_iterator; -#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ - 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; -#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ - -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); - -#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); - -#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(*n, *n + 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()); -} +#ifdef __STL_USE_NAMESPACES +using __STD::deque; +#endif /* __STL_USE_NAMESPACES */ -#endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */ - - #endif /* __SGI_STL_DEQUE_H */ +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/function.h b/libstdc++/stl/function.h index e4f4713235b..6474dd99fa2 100644 --- a/libstdc++/stl/function.h +++ b/libstdc++/stl/function.h @@ -12,7 +12,7 @@ * purpose. It is provided "as is" without express or implied warranty. * * - * Copyright (c) 1996 + * Copyright (c) 1996,1997 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, modify, distribute and sell this software @@ -27,608 +27,92 @@ #ifndef __SGI_STL_FUNCTION_H #define __SGI_STL_FUNCTION_H -#include <stddef.h> +#ifndef __STL_CONFIG_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> +#ifndef __SGI_STL_INTERNAL_RELOPS +#include <stl_relops.h> +#endif +#include <stddef.h> +#ifndef __SGI_STL_INTERNAL_FUNCTION_H +#include <stl_function.h> #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); -} +#ifdef __STL_USE_NAMESPACE_FOR_RELOPS + +// Names from stl_relops.h +using __STD_RELOPS::operator!=; +using __STD_RELOPS::operator>; +using __STD_RELOPS::operator<=; +using __STD_RELOPS::operator>=; + +#endif /* __STL_USE_NAMESPACE_FOR_RELOPS */ + +#ifdef __STL_USE_NAMESPACES + +// Names from stl_function.h +using __STD::unary_function; +using __STD::binary_function; +using __STD::plus; +using __STD::minus; +using __STD::multiplies; +using __STD::divides; +using __STD::identity_element; +using __STD::modulus; +using __STD::negate; +using __STD::equal_to; +using __STD::not_equal_to; +using __STD::greater; +using __STD::less; +using __STD::greater_equal; +using __STD::less_equal; +using __STD::logical_and; +using __STD::logical_or; +using __STD::logical_not; +using __STD::unary_negate; +using __STD::binary_negate; +using __STD::not1; +using __STD::not2; +using __STD::binder1st; +using __STD::binder2nd; +using __STD::bind1st; +using __STD::bind2nd; +using __STD::unary_compose; +using __STD::binary_compose; +using __STD::compose1; +using __STD::compose2; +using __STD::pointer_to_unary_function; +using __STD::pointer_to_binary_function; +using __STD::ptr_fun; +using __STD::identity; +using __STD::select1st; +using __STD::select2nd; +using __STD::project1st; +using __STD::project2nd; +using __STD::constant_void_fun; +using __STD::constant_unary_fun; +using __STD::constant_binary_fun; +using __STD::constant0; +using __STD::constant1; +using __STD::constant2; +using __STD::subtractive_rng; +using __STD::mem_fun_t; +using __STD::const_mem_fun_t; +using __STD::mem_fun_ref_t; +using __STD::const_mem_fun_ref_t; +using __STD::mem_fun1_t; +using __STD::const_mem_fun1_t; +using __STD::mem_fun1_ref_t; +using __STD::const_mem_fun1_ref_t; +using __STD::mem_fun; +using __STD::mem_fun_ref; +using __STD::mem_fun1; +using __STD::mem_fun1_ref; + +#endif /* __STL_USE_NAMESPACES */ #endif /* __SGI_STL_FUNCTION_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/functional b/libstdc++/stl/functional new file mode 100644 index 00000000000..d046dbb036d --- /dev/null +++ b/libstdc++/stl/functional @@ -0,0 +1,26 @@ +/* + * 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_FUNCTIONAL +#define __SGI_STL_FUNCTIONAL + +#include <stl_config.h> +#include <stddef.h> +#include <stl_function.h> + +#endif /* __SGI_STL_FUNCTIONAL */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/hash_map b/libstdc++/stl/hash_map new file mode 100644 index 00000000000..f7421e026fa --- /dev/null +++ b/libstdc++/stl/hash_map @@ -0,0 +1,40 @@ +/* + * 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 +#define __SGI_STL_HASH_MAP + +#ifndef __SGI_STL_INTERNAL_HASHTABLE_H +#include <stl_hashtable.h> +#endif + +#include <stl_hash_map.h> + +#endif /* __SGI_STL_HASH_MAP */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/hash_map.h b/libstdc++/stl/hash_map.h index c52b9936e7b..81cb5784f47 100644 --- a/libstdc++/stl/hash_map.h +++ b/libstdc++/stl/hash_map.h @@ -27,293 +27,22 @@ #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 __SGI_STL_INTERNAL_HASHTABLE_H +#include <stl_hashtable.h> +#endif +#include <stl_hash_map.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; +#ifdef __STL_USE_NAMESPACES +using __STD::hash; +using __STD::hashtable; +using __STD::hash_map; +using __STD::hash_multimap; +#endif /* __STL_USE_NAMESPACES */ -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 */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/hash_set b/libstdc++/stl/hash_set new file mode 100644 index 00000000000..2244f47cfa0 --- /dev/null +++ b/libstdc++/stl/hash_set @@ -0,0 +1,40 @@ +/* + * 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 +#define __SGI_STL_HASH_SET + +#ifndef __SGI_STL_INTERNAL_HASHTABLE_H +#include <stl_hashtable.h> +#endif + +#include <stl_hash_set.h> + +#endif /* __SGI_STL_HASH_SET */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/hash_set.h b/libstdc++/stl/hash_set.h index 2c7125eb7e5..c938ccc467a 100644 --- a/libstdc++/stl/hash_set.h +++ b/libstdc++/stl/hash_set.h @@ -27,280 +27,17 @@ #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; -} - +#ifndef __SGI_STL_INTERNAL_HASHTABLE_H +#include <stl_hashtable.h> +#endif + +#include <stl_hash_set.h> + +#ifdef __STL_USE_NAMESPACES +using __STD::hash; +using __STD::hashtable; +using __STD::hash_set; +using __STD::hash_multiset; +#endif /* __STL_USE_NAMESPACES */ #endif /* __SGI_STL_HASH_SET_H */ diff --git a/libstdc++/stl/hashtable.h b/libstdc++/stl/hashtable.h index fb4abc2b344..15dbfc91644 100644 --- a/libstdc++/stl/hashtable.h +++ b/libstdc++/stl/hashtable.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996 + * Copyright (c) 1996,1997 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, modify, distribute and sell this software @@ -24,969 +24,25 @@ * */ +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + #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 <stl_hashtable.h> #include <algo.h> +#include <alloc.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 Value* pointer; - - node* cur; - hashtable* ht; - - __hashtable_iterator(node* n, hashtable* tab) : cur(n), ht(tab) {} - __hashtable_iterator() {} - reference operator*() const { return cur->val; } -#ifndef __SGI_STL_NO_ARROW_OPERATOR - pointer operator->() const { return &(operator*()); } -#endif /* __SGI_STL_NO_ARROW_OPERATOR */ - 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 const Value& reference; - typedef const 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) {} - reference operator*() const { return cur->val; } -#ifndef __SGI_STL_NO_ARROW_OPERATOR - pointer operator->() const { return &(operator*()); } -#endif /* __SGI_STL_NO_ARROW_OPERATOR */ - 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); - } - -#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; -} - -#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION - -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; -} - -#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ - -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 */ -} - +#ifdef __STL_USE_NAMESPACES +using __STD::hash; +using __STD::hashtable; +#endif /* __STL_USE_NAMESPACES */ #endif /* __SGI_STL_HASHTABLE_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/heap.h b/libstdc++/stl/heap.h index b24afafadd6..2ec93c07b76 100644 --- a/libstdc++/stl/heap.h +++ b/libstdc++/stl/heap.h @@ -11,194 +11,36 @@ * 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_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)); -} +#include <stl_config.h> +#include <stl_heap.h> -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); -} +#ifdef __STL_USE_NAMESPACES -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); -} +using __STD::push_heap; +using __STD::pop_heap; +using __STD::make_heap; +using __STD::sort_heap; -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)); -} +#endif /* __STL_USE_NAMESPACES */ -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 */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/iterator b/libstdc++/stl/iterator new file mode 100644 index 00000000000..90e6c9c8b68 --- /dev/null +++ b/libstdc++/stl/iterator @@ -0,0 +1,40 @@ +/* + * + * 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,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_ITERATOR +#define __SGI_STL_ITERATOR + +#include <stl_config.h> +#include <stl_relops.h> +#include <stddef.h> +#include <iostream.h> +#include <stl_iterator.h> + +#endif /* __SGI_STL_ITERATOR */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/iterator.h b/libstdc++/stl/iterator.h index f8a19d0aa34..f8a02377422 100644 --- a/libstdc++/stl/iterator.h +++ b/libstdc++/stl/iterator.h @@ -27,765 +27,78 @@ #ifndef __SGI_STL_ITERATOR_H #define __SGI_STL_ITERATOR_H +#ifndef __SGI_STL_FUNCTION_H +#include <function.h> +#endif #include <stddef.h> #include <iostream.h> -#include <function.h> - -struct input_iterator_tag {}; -struct output_iterator_tag {}; -struct forward_iterator_tag : public input_iterator_tag {}; -struct bidirectional_iterator_tag : public forward_iterator_tag {}; -struct random_access_iterator_tag : public bidirectional_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; - typedef void value_type; - typedef void difference_type; - typedef void pointer; - typedef void reference; -}; - -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; -}; +#ifndef __SGI_STL_INTERNAL_ITERATOR_H +#include <stl_iterator.h> #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; -}; - -template <class T> -struct iterator_traits<const T*> { - typedef random_access_iterator_tag iterator_category; - typedef T value_type; - typedef ptrdiff_t difference_type; - typedef const T* pointer; - typedef const T& reference; -}; - -template <class Iterator> -inline iterator_traits<Iterator>::iterator_category -iterator_category(const Iterator&) { - return iterator_traits<Iterator>::iterator_category(); -} - -template <class Iterator> -inline iterator_traits<Iterator>::difference_type* -distance_type(const Iterator&) { - return static_cast<iterator_traits<Iterator>::difference_type*>(0); -} - -template <class Iterator> -inline iterator_traits<Iterator>::value_type* -value_type(const Iterator&) { - return static_cast<iterator_traits<Iterator>::value_type*>(0); -} - -#else /* __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); } - -#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ - -template <class Container> -class back_insert_iterator { -protected: - Container* container; -public: - typedef output_iterator_tag iterator_category; - typedef void value_type; - typedef void difference_type; - typedef void pointer; - typedef void reference; - - 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; } -}; - -#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION - -template <class Container> -inline output_iterator_tag -iterator_category(const back_insert_iterator<Container>&) -{ - return output_iterator_tag(); -} - -#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ - -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; - typedef void value_type; - typedef void difference_type; - typedef void pointer; - typedef void reference; - - 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; } -}; - -#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION - -template <class Container> -inline output_iterator_tag -iterator_category(const front_insert_iterator<Container>&) -{ - return output_iterator_tag(); -} - -#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ - -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; - typedef void value_type; - typedef void difference_type; - typedef void pointer; - typedef void reference; - - 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; } -}; - -#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION - -template <class Container> -inline output_iterator_tag -iterator_category(const insert_iterator<Container>&) -{ - return output_iterator_tag(); -} - -#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ - -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> +#ifndef __TYPE_TRAITS_H +#include <type_traits.h> +#endif +#ifndef __SGI_STL_INTERNAL_CONSTRUCT_H +#include <stl_construct.h> +#endif +#ifndef __SGI_STL_INTERNAL_RAW_STORAGE_ITERATOR_H +#include <stl_raw_storage_iter.h> #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; - } -#ifndef __SGI_STL_NO_ARROW_OPERATOR - pointer operator->() const { return &(operator*()); } -#endif /* __SGI_STL_NO_ARROW_OPERATOR */ - 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; - } -}; - -#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION - -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; -} +#ifdef __STL_USE_NAMESPACES -template <class BidirectionalIterator, class T, class Reference, - class Distance> -inline Distance* -distance_type(const reverse_bidirectional_iterator<BidirectionalIterator, T, - Reference, Distance>&) { - return (Distance*) 0; -} +// Names from stl_iterator.h -#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ +using __STD::input_iterator_tag; +using __STD::output_iterator_tag; +using __STD::forward_iterator_tag; +using __STD::bidirectional_iterator_tag; +using __STD::random_access_iterator_tag; -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; -} +#if 0 +using __STD::iterator; +#endif +using __STD::input_iterator; +using __STD::output_iterator; +using __STD::forward_iterator; +using __STD::bidirectional_iterator; +using __STD::random_access_iterator; #ifdef __STL_CLASS_PARTIAL_SPECIALIZATION - -// This is the new version of reverse_iterator, as defined in the -// draft C++ standard. It relies on the iterator_traits template, -// which in turn relies on partial specialization. The class -// reverse_bidirectional_iterator is no longer part of the draft -// standard, but it is retained for backward compatibility. - -template <class Iterator> -class reverse_iterator : public iterator_traits<Iterator> -{ -protected: - Iterator current; -public: - typedef Iterator iterator_type; - typedef reverse_iterator<Iterator> self; - -public: - reverse_iterator() {} - explicit reverse_iterator(iterator_type x) : current(x) {} - - reverse_iterator(const self& x) : current(x.current) {} -#ifdef __STL_MEMBER_TEMPLATES - template <class Iter> - reverse_iterator(const reverse_iterator<Iter>& x) : current(x.current) {} -#endif /* __STL_MEMBER_TEMPLATES */ - - iterator_type base() const { return current; } - reference operator*() const { - Iterator tmp = current; - return *--tmp; - } -#ifndef __SGI_STL_NO_ARROW_OPERATOR - pointer operator->() const { return &(operator*()); } -#endif /* __SGI_STL_NO_ARROW_OPERATOR */ - - 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+(difference_type n) const { - return self(current - n); - } - self& operator+=(difference_type n) { - current -= n; - return *this; - } - self operator-(difference_type n) const { - return self(current + n); - } - self& operator-=(difference_type n) { - current += n; - return *this; - } - reference operator[](difference_type n) { return *(*this + n); } -}; - -template <class Iterator> -inline bool operator==(const reverse_iterator<Iterator>& x, - const reverse_iterator<Iterator>& y) { - return x.base() == y.base(); -} - -template <class Iterator> -inline bool operator<(const reverse_iterator<Iterator>& x, - const reverse_iterator<Iterator>& y) { - return y.base() < x.base(); -} - -template <class Iterator> -inline reverse_iterator<Iterator>::difference_type -operator-(const reverse_iterator<Iterator>& x, - const reverse_iterator<Iterator>& y) { - return y.base() - x.base(); -} - -template <class Iterator> -inline reverse_iterator<Iterator> -operator+(reverse_iterator<Iterator>::difference_type n, - const reverse_iterator<Iterator>& x) { - return reverse_iterator<Iterator>(x.base() - n); -} - -#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ - -// This is the old version of reverse_iterator, as found in the original -// HP STL. It does not use partial specialization. - -#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> +using __STD::iterator_traits; #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); } -#ifndef __SGI_STL_NO_ARROW_OPERATOR - pointer operator->() const { return &(operator*()); } -#endif /* __SGI_STL_NO_ARROW_OPERATOR */ - 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); -} -#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ +using __STD::iterator_category; +using __STD::distance_type; +using __STD::value_type; -template <class ForwardIterator, class T> -class raw_storage_iterator { -protected: - ForwardIterator iter; -public: - typedef output_iterator_tag iterator_category; - typedef void value_type; - typedef void difference_type; - typedef void pointer; - typedef void reference; +using __STD::distance; +using __STD::advance; - 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; - } -}; +using __STD::insert_iterator; +using __STD::front_insert_iterator; +using __STD::back_insert_iterator; +using __STD::inserter; +using __STD::front_inserter; +using __STD::back_inserter; -#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION +using __STD::reverse_iterator; +using __STD::reverse_bidirectional_iterator; -template <class ForwardIterator, class T> -inline output_iterator_tag -iterator_category(const raw_storage_iterator<ForwardIterator, T>&) -{ - return output_iterator_tag(); -} +using __STD::istream_iterator; +using __STD::ostream_iterator; -#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ +// Names from stl_construct.h +using __STD::construct; +using __STD::destroy; -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 const T* pointer; - typedef const T& reference; +// Names from stl_raw_storage_iter.h +using __STD::raw_storage_iterator; - istream_iterator() : stream(&cin), end_marker(false) {} - istream_iterator(istream& s) : stream(&s) { read(); } - reference operator*() const { return value; } -#ifndef __SGI_STL_NO_ARROW_OPERATOR - pointer operator->() const { return &(operator*()); } -#endif /* __SGI_STL_NO_ARROW_OPERATOR */ - istream_iterator<T, Distance>& operator++() { - read(); - return *this; - } - istream_iterator<T, Distance> operator++(int) { - istream_iterator<T, Distance> tmp = *this; - read(); - return tmp; - } -}; - -#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION - -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; -} - -#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ - -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; - typedef void value_type; - typedef void difference_type; - typedef void pointer; - typedef void reference; - - 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; } -}; - -#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION - -template <class T> -inline output_iterator_tag -iterator_category(const ostream_iterator<T>&) { - return output_iterator_tag(); -} - -#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ +#endif /* __STL_USE_NAMESPACES */ #endif /* __SGI_STL_ITERATOR_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/list b/libstdc++/stl/list new file mode 100644 index 00000000000..5294f39fea6 --- /dev/null +++ b/libstdc++/stl/list @@ -0,0 +1,40 @@ +/* + * + * 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,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_LIST +#define __SGI_STL_LIST + +#include <stl_algobase.h> +#include <stl_alloc.h> +#include <stl_construct.h> +#include <stl_uninitialized.h> +#include <stl_list.h> + +#endif /* __SGI_STL_LIST */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/list.h b/libstdc++/stl/list.h index 6d9492865e8..4e6ee0b4113 100644 --- a/libstdc++/stl/list.h +++ b/libstdc++/stl/list.h @@ -12,7 +12,7 @@ * purpose. It is provided "as is" without express or implied warranty. * * - * Copyright (c) 1996 + * Copyright (c) 1996,1997 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, modify, distribute and sell this software @@ -27,608 +27,16 @@ #ifndef __SGI_STL_LIST_H #define __SGI_STL_LIST_H -#include <stddef.h> #include <algobase.h> -#include <iterator.h> #include <alloc.h> +#include <stl_list.h> -template <class T> -struct __list_node { - typedef void* void_pointer; - void_pointer next; - void_pointer prev; - T data; -}; - -template<class T, class Ref, class Ptr> -struct __list_iterator { - typedef __list_iterator<T, T&, T*> iterator; - typedef __list_iterator<T, const T&, const T*> const_iterator; - typedef __list_iterator<T, Ref, Ptr> self; - - typedef bidirectional_iterator_tag iterator_category; - typedef T value_type; - typedef Ptr pointer; - typedef Ref 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; } - reference operator*() const { return (*node).data; } - -#ifndef __SGI_STL_NO_ARROW_OPERATOR - pointer operator->() const { return &(operator*()); } -#endif /* __SGI_STL_NO_ARROW_OPERATOR */ - - 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; - } -}; - -#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION - -template <class T, class Ref, class Ptr> -inline bidirectional_iterator_tag -iterator_category(const __list_iterator<T, Ref, Ptr>&) { - return bidirectional_iterator_tag(); -} - -template <class T, class Ref, class Ptr> -inline T* -value_type(const __list_iterator<T, Ref, Ptr>&) { - return 0; -} - -template <class T, class Ref, class Ptr> -inline ptrdiff_t* -distance_type(const __list_iterator<T, Ref, Ptr>&) { - return 0; -} - -#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ - -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&, T*> iterator; - typedef __list_iterator<T, const T&, const T*> const_iterator; - -#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION - typedef reverse_iterator<const_iterator> const_reverse_iterator; - typedef reverse_iterator<iterator> reverse_iterator; -#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ - 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; -#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ - -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 */ +#ifdef __STL_USE_NAMESPACES +using __STD::list; +#endif /* __STL_USE_NAMESPACES */ #endif /* __SGI_STL_LIST_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/map b/libstdc++/stl/map new file mode 100644 index 00000000000..4cfb7652c54 --- /dev/null +++ b/libstdc++/stl/map @@ -0,0 +1,40 @@ +/* + * + * 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,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_MAP +#define __SGI_STL_MAP + +#ifndef __SGI_STL_INTERNAL_TREE_H +#include <stl_tree.h> +#endif +#include <stl_map.h> +#include <stl_multimap.h> + +#endif /* __SGI_STL_MAP */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/map.h b/libstdc++/stl/map.h index 5c9d6b1bf3b..a89bd31e81c 100644 --- a/libstdc++/stl/map.h +++ b/libstdc++/stl/map.h @@ -12,7 +12,7 @@ * purpose. It is provided "as is" without express or implied warranty. * * - * Copyright (c) 1996 + * Copyright (c) 1996,1997 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, modify, distribute and sell this software @@ -28,161 +28,14 @@ #define __SGI_STL_MAP_H #include <tree.h> +#include <stl_map.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; -} +#ifdef __STL_USE_NAMESPACES +using __STD::map; +#endif /* __STL_USE_NAMESPACES */ #endif /* __SGI_STL_MAP_H */ +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/memory b/libstdc++/stl/memory new file mode 100644 index 00000000000..a80658875ee --- /dev/null +++ b/libstdc++/stl/memory @@ -0,0 +1,89 @@ +/* + * 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_MEMORY +#define __SGI_STL_MEMORY + +#include <stl_algobase.h> +#include <stl_alloc.h> +#include <stl_construct.h> +#include <stl_tempbuf.h> +#include <stl_uninitialized.h> +#include <stl_raw_storage_iter.h> + +// Note: auto_ptr is commented out in this release because the details +// of the interface are still being discussed by the C++ standardization +// committee. It will be included once the iterface is finalized. + +#if 0 +#if defined(_MUTABLE_IS_KEYWORD) && defined(_EXPLICIT_IS_KEYWORD) && \ + defined(__STL_MEMBER_TEMPLATES) + +__STL_BEGIN_NAMESPACE + +template <class X> class auto_ptr { +private: + X* ptr; + mutable bool owns; +public: + typedef X element_type; + explicit auto_ptr(X* p = 0) __STL_NOTHROW : ptr(p), owns(p) {} + auto_ptr(const auto_ptr& a) __STL_NOTHROW : ptr(a.ptr), owns(a.owns) { + a.owns = 0; + } + template <class T> auto_ptr(const auto_ptr<T>& a) __STL_NOTHROW + : ptr(a.ptr), owns(a.owns) { + a.owns = 0; + } + + auto_ptr& operator=(const auto_ptr& a) __STL_NOTHROW { + if (&a != this) { + if (owns) + delete ptr; + owns = a.owns; + ptr = a.ptr; + a.owns = 0; + } + } + template <class T> auto_ptr& operator=(const auto_ptr<T>& a) __STL_NOTHROW { + if (&a != this) { + if (owns) + delete ptr; + owns = a.owns; + ptr = a.ptr; + a.owns = 0; + } + } + ~auto_ptr() { + if (owns) + delete ptr; + } + + X& operator*() const __STL_NOTHROW { return *ptr; } + X* operator->() const __STL_NOTHROW { return ptr; } + X* get() const __STL_NOTHROW { return ptr; } + X* release const __STL_NOTHROW { owns = false; return ptr } +}; + +__STL_END_NAMESPACE +#endif /* mutable && explicit && member templates */ +#endif /* 0 */ + + +#endif /* __SGI_STL_MEMORY */ + + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/multimap.h b/libstdc++/stl/multimap.h index f15880af39d..1a8ec4af4f9 100644 --- a/libstdc++/stl/multimap.h +++ b/libstdc++/stl/multimap.h @@ -12,7 +12,7 @@ * purpose. It is provided "as is" without express or implied warranty. * * - * Copyright (c) 1996 + * Copyright (c) 1996,1997 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, modify, distribute and sell this software @@ -28,155 +28,14 @@ #define __SGI_STL_MULTIMAP_H #include <tree.h> +#include <stl_multimap.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; -} +#ifdef __STL_USE_NAMESPACES +using __STD::multimap; +#endif /* __STL_USE_NAMESPACES */ #endif /* __SGI_STL_MULTIMAP_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/multiset.h b/libstdc++/stl/multiset.h index 3df4557b18f..3024fd74c03 100644 --- a/libstdc++/stl/multiset.h +++ b/libstdc++/stl/multiset.h @@ -12,7 +12,7 @@ * purpose. It is provided "as is" without express or implied warranty. * * - * Copyright (c) 1996 + * Copyright (c) 1996,1997 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, modify, distribute and sell this software @@ -28,140 +28,14 @@ #define __SGI_STL_MULTISET_H #include <tree.h> +#include <stl_multiset.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; -} +#ifdef __STL_USE_NAMESPACES +using __STD::multiset; +#endif /* __STL_USE_NAMESPACES */ #endif /* __SGI_STL_MULTISET_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/numeric b/libstdc++/stl/numeric new file mode 100644 index 00000000000..7f048e11b56 --- /dev/null +++ b/libstdc++/stl/numeric @@ -0,0 +1,42 @@ +/* + * + * 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,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_NUMERIC +#define __SGI_STL_NUMERIC + +#include <stl_config.h> +#include <stl_relops.h> +#include <stddef.h> +#include <iostream.h> +#include <stl_iterator.h> +#include <stl_function.h> +#include <stl_numeric.h> + +#endif /* __SGI_STL_NUMERIC */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/pair.h b/libstdc++/stl/pair.h index ca20d8baf8a..00f5caddb61 100644 --- a/libstdc++/stl/pair.h +++ b/libstdc++/stl/pair.h @@ -12,7 +12,7 @@ * purpose. It is provided "as is" without express or implied warranty. * * - * Copyright (c) 1996 + * Copyright (c) 1996,1997 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, modify, distribute and sell this software @@ -24,40 +24,28 @@ * purpose. It is provided "as is" without express or implied warranty. */ -#ifndef PAIR_H -#define PAIR_H +#ifndef __SGI_STL_PAIR_H +#define __SGI_STL_PAIR_H +#ifndef __STL_CONFIG_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 -}; +#ifndef __SGI_STL_INTERNAL_RELOPS +#include <stl_relops.h> +#endif +#ifndef __SGI_STL_INTERNAL_PAIR_H +#include <stl_pair.h> +#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; -} +#ifdef __STL_USE_NAMESPACES -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); -} +using __STD::pair; +using __STD::make_pair; -template <class T1, class T2> -inline pair<T1, T2> make_pair(const T1& x, const T2& y) { - return pair<T1, T2>(x, y); -} +#endif /* __STL_USE_NAMESPACES */ -#endif +#endif /* __SGI_STL_PAIR_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/pthread_alloc b/libstdc++/stl/pthread_alloc new file mode 100644 index 00000000000..71df3d3b548 --- /dev/null +++ b/libstdc++/stl/pthread_alloc @@ -0,0 +1,347 @@ +/* + * 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_PTHREAD_ALLOC +#define __SGI_STL_PTHREAD_ALLOC + +// 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 <stl_config.h> +#include <stl_alloc.h> +#ifndef __RESTRICT +# define __RESTRICT +#endif + +__STL_BEGIN_NAMESPACE + +// 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; + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_PTHREAD_ALLOC */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/pthread_alloc.h b/libstdc++/stl/pthread_alloc.h index a2aeaa1290e..0a2debb74bd 100644 --- a/libstdc++/stl/pthread_alloc.h +++ b/libstdc++/stl/pthread_alloc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996 + * Copyright (c) 1996-1997 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, modify, distribute and sell this software @@ -11,334 +11,21 @@ * purpose. It is provided "as is" without express or implied warranty. */ -#ifndef __PTHREAD_ALLOC_H -#define __PTHREAD_ALLOC_H +#ifndef __SGI_STL_PTHREAD_ALLOC_H +#define __SGI_STL_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 <pthread_alloc> +#ifdef __STL_USE_NAMESPACES -#include <stddef.h> -#include <stdlib.h> -#include <string.h> -#include <pthread.h> -#include <alloc.h> -#ifndef __RESTRICT -# define __RESTRICT -#endif +using __STD::__pthread_alloc_template; +using __STL::pthread_alloc; -// Note that this class has nonstatic members. We instantiate it once -// per thread. -template <bool dummy> -class __pthread_alloc_template { +#endif /* __STL_USE_NAMESPACES */ -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. */ - }; +#endif /* __SGI_STL_PTHREAD_ALLOC_H */ - // 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 */ +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/queue b/libstdc++/stl/queue new file mode 100644 index 00000000000..f9417fb1fbb --- /dev/null +++ b/libstdc++/stl/queue @@ -0,0 +1,45 @@ +/* + * + * 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,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_QUEUE +#define __SGI_STL_QUEUE + +#include <stl_algobase.h> +#include <stl_alloc.h> +#include <stl_construct.h> +#include <stl_uninitialized.h> +#include <stl_vector.h> +#include <stl_bvector.h> +#include <stl_heap.h> +#include <stl_deque.h> +#include <stl_function.h> +#include <stl_queue.h> + +#endif /* __SGI_STL_QUEUE */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/rope b/libstdc++/stl/rope new file mode 100644 index 00000000000..9ef738241d7 --- /dev/null +++ b/libstdc++/stl/rope @@ -0,0 +1,32 @@ +/* + * 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_ROPE +#define __SGI_STL_ROPE + +#include <stl_algobase.h> +#include <tempbuf.h> +#include <stl_algo.h> +#include <stl_function.h> +#include <stl_numeric.h> +#include <stl_alloc.h> +#include <stl_construct.h> +#include <stl_uninitialized.h> +#include <stl_hash_fun.h> +#include <stl_rope.h> + +#endif /* __SGI_STL_ROPE */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/rope.h b/libstdc++/stl/rope.h index 399352f477e..d767fa32e7a 100644 --- a/libstdc++/stl/rope.h +++ b/libstdc++/stl/rope.h @@ -11,2066 +11,24 @@ * purpose. It is provided "as is" without express or implied warranty. */ -#ifndef _ROPE_H -# define _ROPE_H +#ifndef __SGI_STL_ROPE_H +#define __SGI_STL_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 +#include <hashtable.h> +#include <stl_rope.h> -// 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(); } +#ifdef __STL_USE_NAMESPACES -// Test for basic character types. -// For basic character types leaves having a trailing eos. -template <class charT> -inline bool __is_basic_char_type(charT *) { return false; } -template <class charT> -inline bool __is_one_byte_char_type(charT *) { return false; } +using __STD::char_producer; +using __STD::sequence_buffer; +using __STD::rope; +using __STD::crope; +using __STD::wrope; -inline bool __is_basic_char_type(char *) { return true; } -inline bool __is_one_byte_char_type(char *) { return true; } -inline bool __is_basic_char_type(wchar_t *) { return true; } +#endif /* __STL_USE_NAMESPACES */ -// 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&) {} +#endif /* __SGI_STL_ROPE_H */ -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<charT, Alloc> DataAlloc; - 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(); - } - static void free_if_unref(__rope_RopeBase* t) - { - if (0 != t && 0 == t -> refcount) t -> free_tree(); - } -# 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 *); - static void free_if_unref(__rope_RopeBase* t) {} -# 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; - } else { - size_with_eos = n; - } -# 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: - typedef charT reference; // Really a value. Returning a reference - // Would be a mess, since it would have - // to be included in refcount. - typedef const charT* pointer; - - 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); - } - reference 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); - reference 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: - typedef __rope_charT_ref_proxy<charT,Alloc> reference; - typedef __rope_charT_ref_proxy<charT,Alloc>* pointer; - - 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); - } - reference 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); - } - reference 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 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<charT, Alloc> DataAlloc; - 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 = DataAlloc::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). - - static RopeLeaf * RopeLeaf_from_unowned_char_ptr(const charT *s, - size_t size) { - charT * buf = alloc_copy(s, size); - __STL_TRY - return RopeLeaf_from_char_ptr(buf, size); - __STL_UNWIND(RopeBase::free_string(buf, 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<rope<charT,Alloc>, rope<charT,Alloc>, - rope<charT,Alloc> > { - rope operator() (const rope& x, const rope& y) { - return x + y; - } - }; - - friend rope identity_element(concat_fn) { return rope<charT,Alloc>(); } - - 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_unowned_char_ptr(s, 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_unowned_char_ptr(s, len); - } - } - - rope(const charT *s, charT *e) - { - size_t len = e - s; - - if (0 == len) { - tree_ptr = 0; - } else { - tree_ptr = RopeLeaf_from_unowned_char_ptr(s, 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 = DataAlloc::allocate(rounded_up_size(1)); - - construct(buf, c); - __STL_TRY - tree_ptr = RopeLeaf_from_char_ptr(buf, 1); - __STL_UNWIND(RopeBase::free_string(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_unowned_char_ptr(i, 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(charT x) - { - RopeBase *old = tree_ptr; - RopeBase *left; - - left = RopeLeaf_from_unowned_char_ptr(&x, 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. - } - -# ifdef __STL_CLASS_PARTIAL_SPECIALIZATION - typedef reverse_iterator<const_iterator> const_reverse_iterator; -# else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ - typedef reverse_iterator<const_iterator, value_type, const_reference, - difference_type> const_reverse_iterator; -# endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ - - 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())); - } - -# ifdef __STL_CLASS_PARTIAL_SPECIALIZATION - typedef reverse_iterator<iterator> reverse_iterator; -# else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ - typedef reverse_iterator<iterator, value_type, reference, - difference_type> reverse_iterator; -# endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ - - 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 */ +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/ropeimpl.h b/libstdc++/stl/ropeimpl.h index d1c1ed4e689..dcd6bfd5117 100644 --- a/libstdc++/stl/ropeimpl.h +++ b/libstdc++/stl/ropeimpl.h @@ -11,9 +11,19 @@ * purpose. It is provided "as is" without express or implied warranty. */ +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + # include <stdio.h> # include <iostream.h> +__STL_BEGIN_NAMESPACE + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma set woff 1174 +#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 @@ -416,8 +426,9 @@ rope<charT,Alloc>::leaf_concat_char_iter 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 + __STL_TRY { result = RopeLeaf_from_char_ptr(new_data, old_len + len); + } __STL_UNWIND(RopeBase::free_string(new_data, old_len + len)); return result; } @@ -482,7 +493,7 @@ rope<charT,Alloc>::tree_concat (RopeBase * left, RopeBase * right) if (depth > 20 && (rsize < 1000 || depth > RopeBase::max_rope_depth)) { RopeBase * balanced; - __STL_TRY + __STL_TRY { balanced = balance(result); # ifndef __GC if (result != balanced) { @@ -491,6 +502,7 @@ rope<charT,Alloc>::tree_concat (RopeBase * left, RopeBase * right) } # endif result -> unref_nonnil(); + } __STL_UNWIND(CAlloc::deallocate(result)); // In case of exception, we need to deallocate // otherwise dangling result node. But caller @@ -526,8 +538,9 @@ rope<charT,Alloc>::RopeBase * rope<charT,Alloc>::concat_char_iter RopeBase * left = ((RopeConcatenation *)r) -> left; RopeBase * nright = leaf_concat_char_iter((RopeLeaf *)right, s, slen); left -> ref_nonnil(); - __STL_TRY + __STL_TRY { result = tree_concat(left, nright); + } __STL_UNWIND(unref(left); unref(nright)); # ifndef __GC __stl_assert(1 == result -> refcount); @@ -536,9 +549,10 @@ rope<charT,Alloc>::RopeBase * rope<charT,Alloc>::concat_char_iter } } RopeBase * nright = RopeLeaf_from_unowned_char_ptr(s, slen); - __STL_TRY + __STL_TRY { r -> ref_nonnil(); result = tree_concat(r, nright); + } __STL_UNWIND(unref(r); unref(nright)); # ifndef __GC __stl_assert(1 == result -> refcount); @@ -591,8 +605,9 @@ rope<charT,Alloc>::RopeBase * rope<charT,Alloc> } RopeBase *right = RopeLeaf_from_unowned_char_ptr(s, slen); r -> ref_nonnil(); - __STL_TRY + __STL_TRY { result = tree_concat(r, right); + } __STL_UNWIND(unref(r); unref(right)) __stl_assert(1 == result -> refcount); return result; @@ -629,16 +644,18 @@ rope<charT,Alloc>::concat(RopeBase * left, RopeBase * right) ((RopeLeaf *)right) -> data, right -> size); leftleft -> ref_nonnil(); - __STL_TRY + __STL_TRY { return(tree_concat(leftleft, rest)); + } __STL_UNWIND(unref(leftleft); unref(rest)) } } } left -> ref_nonnil(); right -> ref_nonnil(); - __STL_TRY + __STL_TRY { return(tree_concat(left, right)); + } __STL_UNWIND(unref(left); unref(right)); } @@ -732,8 +749,9 @@ rope<charT,Alloc>::substring(RopeBase * base, size_t start, size_t endp1) if (result_len > lazy_threshold) goto lazy; section = (charT *) DataAlloc::allocate(rounded_up_size(result_len)); - __STL_TRY + __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); @@ -872,10 +890,12 @@ bool rope<charT, Alloc>::apply_to_pieces( size_t len = end - begin; bool result; charT * buffer = DataAlloc::allocate(len); - __STL_TRY + __STL_TRY { (*(f -> fn))(begin, end, buffer); result = c(buffer, len); - __STL_ALWAYS(DataAlloc::deallocate(buffer, len)) + DataAlloc::deallocate(buffer, len); + } + __STL_UNWIND(DataAlloc::deallocate(buffer, len)) return result; } default: @@ -915,7 +935,7 @@ ostream& operator<< (ostream& o, const rope<charT, Alloc>& r) pad_len = 0; } if (!is_simple) o.width(w/rope_len); - __STL_TRY + __STL_TRY { if (is_simple && !left && pad_len > 0) { __rope_fill(o, pad_len); } @@ -923,7 +943,10 @@ ostream& operator<< (ostream& o, const rope<charT, Alloc>& r) if (is_simple && left && pad_len > 0) { __rope_fill(o, pad_len); } - __STL_ALWAYS(if (!is_simple) o.width(w)) + if (!is_simple) + o.width(w); + } + __STL_UNWIND(if (!is_simple) o.width(w)) return o; } @@ -964,7 +987,7 @@ rope<charT,Alloc>::flatten(RopeBase * r, charT * buffer) case RopeBase::leaf: { RopeLeaf * l = (RopeLeaf *)r; - return copy_n(l -> data, l -> size, buffer); + return copy_n(l -> data, l -> size, buffer).second; } case RopeBase::function: case RopeBase::substringfn: @@ -1076,7 +1099,7 @@ rope<charT,Alloc>::balance(RopeBase *r) // References from forest are included in refcount. for (i = 0; i <= RopeBase::max_rope_depth; ++i) forest[i] = 0; - __STL_TRY + __STL_TRY { add_to_forest(r, forest); for (i = 0; i <= RopeBase::max_rope_depth; ++i) if (0 != forest[i]) { # ifndef __GC @@ -1088,6 +1111,7 @@ rope<charT,Alloc>::balance(RopeBase *r) forest[i] = 0; # endif } + } __STL_UNWIND(for(i = 0; i <= RopeBase::max_rope_depth; i++) unref(forest[i])) if (result -> depth > RopeBase::max_rope_depth) abort(); @@ -1366,8 +1390,9 @@ rope<charT, Alloc>::rope(size_t n, charT c) rest_buffer = DataAlloc::allocate(rounded_up_size(rest)); uninitialized_fill_n(rest_buffer, rest, c); __cond_store_eos(rest_buffer[rest]); - __STL_TRY + __STL_TRY { remainder = RopeLeaf_from_char_ptr(rest_buffer, rest); + } __STL_UNWIND(RopeBase::free_string(rest_buffer, rest)) } remainder_rope.tree_ptr = remainder; @@ -1378,9 +1403,10 @@ rope<charT, Alloc>::rope(size_t n, charT c) rope base_rope; 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_TRY { + base_leaf = RopeLeaf_from_char_ptr(base_buffer, + exponentiate_threshold); + } __STL_UNWIND(RopeBase::free_string(base_buffer, exponentiate_threshold)) base_rope.tree_ptr = base_leaf; if (1 == exponent) { @@ -1499,3 +1525,13 @@ inline void rotate(__rope_iterator<wchar_t,__ALLOC> first, } # endif #endif /* _MSC_VER */ + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma reset woff 1174 +#endif + +__STL_END_NAMESPACE + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/set b/libstdc++/stl/set new file mode 100644 index 00000000000..c836c4596d2 --- /dev/null +++ b/libstdc++/stl/set @@ -0,0 +1,40 @@ +/* + * + * 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,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_SET +#define __SGI_STL_SET + +#ifndef __SGI_STL_INTERNAL_TREE_H +#include <stl_tree.h> +#endif +#include <stl_set.h> +#include <stl_multiset.h> + +#endif /* __SGI_STL_SET */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/set.h b/libstdc++/stl/set.h index 6a79a625653..9004d2e0477 100644 --- a/libstdc++/stl/set.h +++ b/libstdc++/stl/set.h @@ -12,7 +12,7 @@ * purpose. It is provided "as is" without express or implied warranty. * * - * Copyright (c) 1996 + * Copyright (c) 1996,1997 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, modify, distribute and sell this software @@ -28,140 +28,14 @@ #define __SGI_STL_SET_H #include <tree.h> +#include <stl_set.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; -} +#ifdef __STL_USE_NAMESPACES +using __STD::set; +#endif /* __STL_USE_NAMESPACES */ #endif /* __SGI_STL_SET_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/slist b/libstdc++/stl/slist new file mode 100644 index 00000000000..c3ec74204c5 --- /dev/null +++ b/libstdc++/stl/slist @@ -0,0 +1,28 @@ +/* + * 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 +#define __SGI_STL_SLIST + +#include <stl_algobase.h> +#include <stl_alloc.h> +#include <stl_construct.h> +#include <stl_uninitialized.h> +#include <stl_slist.h> + +#endif /* __SGI_STL_SLIST */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/slist.h b/libstdc++/stl/slist.h index 9ae6e117f0d..d2377b0cf5a 100644 --- a/libstdc++/stl/slist.h +++ b/libstdc++/stl/slist.h @@ -17,720 +17,14 @@ #include <algobase.h> #include <alloc.h> +#include <stl_slist.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, class Ptr> -struct __slist_iterator : public __slist_iterator_base -{ - typedef __slist_iterator<T, T&, T*> iterator; - typedef __slist_iterator<T, const T&, const T*> const_iterator; - typedef __slist_iterator<T, Ref, Ptr> self; - - typedef T value_type; - typedef Ptr pointer; - typedef Ref 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) {} - - reference operator*() const { return ((list_node*) node)->data; } -#ifndef __SGI_STL_NO_ARROW_OPERATOR - pointer operator->() const { return &(operator*()); } -#endif /* __SGI_STL_NO_ARROW_OPERATOR */ - - self& operator++() - { - incr(); - return *this; - } - self operator++(int) - { - self tmp = *this; - incr(); - return tmp; - } -}; - -#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION - -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, class Ptr> -inline T* -value_type(const __slist_iterator<T, Ref, Ptr>&) { - return 0; -} - -#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ - -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, T&, T*> iterator; - typedef __slist_iterator<T, const T&, const T*> 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 */ +#ifdef __STL_USE_NAMESPACES +using __STD::slist; +#endif /* __STL_USE_NAMESPACES */ #endif /* __SGI_STL_SLIST_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stack b/libstdc++/stl/stack new file mode 100644 index 00000000000..36461d95b8c --- /dev/null +++ b/libstdc++/stl/stack @@ -0,0 +1,41 @@ +/* + * + * 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,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_STACK +#define __SGI_STL_STACK + +#include <stl_algobase.h> +#include <stl_alloc.h> +#include <stl_construct.h> +#include <stl_uninitialized.h> +#include <stl_deque.h> +#include <stl_stack.h> + +#endif /* __SGI_STL_STACK */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stack.h b/libstdc++/stl/stack.h index cc025bb70e1..89beca82f12 100644 --- a/libstdc++/stl/stack.h +++ b/libstdc++/stl/stack.h @@ -12,7 +12,7 @@ * purpose. It is provided "as is" without express or implied warranty. * * - * Copyright (c) 1996 + * Copyright (c) 1996,1997 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, modify, distribute and sell this software @@ -24,148 +24,23 @@ * purpose. It is provided "as is" without express or implied warranty. */ -#ifndef STACK_H -#define STACK_H +#ifndef __SGI_STL_STACK_H +#define __SGI_STL_STACK_H -#include <function.h> -#include <heap.h> #include <vector.h> #include <deque.h> +#include <heap.h> +#include <stl_stack.h> +#include <stl_queue.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 */ - } -}; +#ifdef __STL_USE_NAMESPACES +using __STD::stack; +using __STD::queue; +using __STD::priority_queue; +#endif /* __STL_USE_NAMESPACES */ -// no equality is provided +#endif /* __SGI_STL_STACK_H */ -#endif +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_algo.h b/libstdc++/stl/stl_algo.h new file mode 100644 index 00000000000..6703c2aa7a8 --- /dev/null +++ b/libstdc++/stl/stl_algo.h @@ -0,0 +1,2674 @@ +/* + * + * 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. + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_ALGO_H +#define __SGI_STL_INTERNAL_ALGO_H + +#include <stl_heap.h> + +__STL_BEGIN_NAMESPACE + +#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> +typename iterator_traits<InputIterator>::difference_type +count(InputIterator first, InputIterator last, const T& value) { + typename iterator_traits<InputIterator>::difference_type n = 0; + for ( ; first != last; ++first) + if (*first == value) + ++n; + return n; +} + +template <class InputIterator, class Predicate> +typename iterator_traits<InputIterator>::difference_type +count_if(InputIterator first, InputIterator last, Predicate pred) { + typename 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 ForwardIterator, class Integer, class T> +ForwardIterator search_n(ForwardIterator first, ForwardIterator last, + Integer count, const T& value) { + if (count <= 0) + return first; + else { + first = find(first, last, value); + while (first != last) { + Integer n = count - 1; + ForwardIterator i = first; + ++i; + while (i != last && n != 0 && *i == value) { + ++i; + --n; + } + if (n == 0) + return first; + else + first = find(i, last, value); + } + return last; + } +} + +template <class ForwardIterator, class Integer, class T, class BinaryPredicate> +ForwardIterator search_n(ForwardIterator first, ForwardIterator last, + Integer count, const T& value, + BinaryPredicate binary_pred) { + if (count <= 0) + return first; + else { + while (first != last) { + if (binary_pred(*first, value)) break; + ++first; + } + while (first != last) { + Integer n = count - 1; + ForwardIterator i = first; + ++i; + while (i != last && n != 0 && binary_pred(*i, value)) { + ++i; + --n; + } + if (n == 0) + return first; + else { + while (i != last) { + if (binary_pred(*i, value)) break; + ++i; + } + first = i; + } + } + return last; + } +} + +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 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 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 (true) { + 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> +inline Size __lg(Size n) { + Size k; + for (k = 0; n != 1; n >>= 1) ++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 >> 1; + middle = first; + advance(middle, half); + if (*middle < value) { + first = middle; + ++first; + len = len - half - 1; + } + else + len = half; + } + return first; +} + +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 >> 1; + 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 >> 1; + middle = first; + advance(middle, half); + if (comp(*middle, value)) { + first = middle; + ++first; + len = len - half - 1; + } + else + len = half; + } + return first; +} + +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 >> 1; + 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 >> 1; + middle = first; + advance(middle, half); + if (value < *middle) + len = half; + else { + first = middle; + ++first; + len = len - half - 1; + } + } + return first; +} + +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 >> 1; + 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 >> 1; + middle = first; + advance(middle, half); + if (comp(value, *middle)) + len = half; + else { + first = middle; + ++first; + len = len - half - 1; + } + } + return first; +} + +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 >> 1; + 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 >> 1; + 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 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 >> 1; + 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 >> 1; + 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 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 >> 1; + 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 ForwardIterator> +InputIterator find_first_of(InputIterator first1, InputIterator last1, + ForwardIterator first2, ForwardIterator last2) +{ + for ( ; first1 != last1; ++first1) + for (ForwardIterator iter = first2; iter != last2; ++iter) + if (*first1 == *iter) + return first1; + return last1; +} + +template <class InputIterator, class ForwardIterator, class BinaryPredicate> +InputIterator find_first_of(InputIterator first1, InputIterator last1, + ForwardIterator first2, ForwardIterator last2, + BinaryPredicate comp) +{ + for ( ; first1 != last1; ++first1) + for (ForwardIterator iter = first2; iter != last2; ++iter) + if (comp(*first1, *iter)) + return first1; + return last1; +} + + +// Search [first2, last2) as a subsequence in [first1, last1). + +// find_end for forward iterators. +template <class ForwardIterator1, class ForwardIterator2> +ForwardIterator1 __find_end(ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + forward_iterator_tag, forward_iterator_tag) +{ + if (first2 == last2) + return last1; + else { + ForwardIterator1 result = last1; + while (1) { + ForwardIterator1 new_result = search(first1, last1, first2, last2); + if (new_result == last1) + return result; + else { + result = new_result; + first1 = new_result; + ++first1; + } + } + } +} + +template <class ForwardIterator1, class ForwardIterator2, + class BinaryPredicate> +ForwardIterator1 __find_end(ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + forward_iterator_tag, forward_iterator_tag, + BinaryPredicate comp) +{ + if (first2 == last2) + return last1; + else { + ForwardIterator1 result = last1; + while (1) { + ForwardIterator1 new_result = search(first1, last1, first2, last2, comp); + if (new_result == last1) + return result; + else { + result = new_result; + first1 = new_result; + ++first1; + } + } + } +} + +// find_end for bidirectional iterators. Requires partial specialization. +#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION + +template <class BidirectionalIterator1, class BidirectionalIterator2> +BidirectionalIterator1 +__find_end(BidirectionalIterator1 first1, BidirectionalIterator1 last1, + BidirectionalIterator2 first2, BidirectionalIterator2 last2, + bidirectional_iterator_tag, bidirectional_iterator_tag) +{ + typedef reverse_iterator<BidirectionalIterator1> reviter1; + typedef reverse_iterator<BidirectionalIterator2> reviter2; + + reviter1 rlast1(first1); + reviter2 rlast2(first2); + reviter1 rresult = search(reviter1(last1), rlast1, reviter2(last2), rlast2); + + if (rresult == rlast1) + return last1; + else { + BidirectionalIterator1 result = rresult.base(); + advance(result, -distance(first2, last2)); + return result; + } +} + +template <class BidirectionalIterator1, class BidirectionalIterator2, + class BinaryPredicate> +BidirectionalIterator1 +__find_end(BidirectionalIterator1 first1, BidirectionalIterator1 last1, + BidirectionalIterator2 first2, BidirectionalIterator2 last2, + bidirectional_iterator_tag, bidirectional_iterator_tag, + BinaryPredicate comp) +{ + typedef reverse_iterator<BidirectionalIterator1> reviter1; + typedef reverse_iterator<BidirectionalIterator2> reviter2; + + reviter1 rlast1(first1); + reviter2 rlast2(first2); + reviter1 rresult = search(reviter1(last1), rlast1, reviter2(last2), rlast2, + comp); + + if (rresult == rlast1) + return last1; + else { + BidirectionalIterator1 result = rresult.base(); + advance(result, -distance(first2, last2)); + return result; + } +} +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +// Dispatching functions. + +template <class ForwardIterator1, class ForwardIterator2> +inline ForwardIterator1 +find_end(ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2) +{ +#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION + typedef typename iterator_traits<ForwardIterator1>::iterator_category + category1; + typedef typename iterator_traits<ForwardIterator2>::iterator_category + category2; + return __find_end(first1, last1, first2, last2, category1(), category2()); +#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + return __find_end(first1, last1, first2, last2, + forward_iterator_tag(), forward_iterator_tag()); +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ +} + +template <class ForwardIterator1, class ForwardIterator2, + class BinaryPredicate> +inline ForwardIterator1 +find_end(ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + BinaryPredicate comp) +{ +#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION + typedef typename iterator_traits<ForwardIterator1>::iterator_category + category1; + typedef typename iterator_traits<ForwardIterator2>::iterator_category + category2; + return __find_end(first1, last1, first2, last2, category1(), category2(), + comp); +#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + return __find_end(first1, last1, first2, last2, + forward_iterator_tag(), forward_iterator_tag(), + comp); +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ +} + +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 & 1 == 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 & 1 == 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 + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_INTERNAL_ALGO_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_algobase.h b/libstdc++/stl/stl_algobase.h new file mode 100644 index 00000000000..668baad8d6b --- /dev/null +++ b/libstdc++/stl/stl_algobase.h @@ -0,0 +1,439 @@ +/* + * + * 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. + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + + +#ifndef __SGI_STL_INTERNAL_ALGOBASE_H +#define __SGI_STL_INTERNAL_ALGOBASE_H + +#ifndef __STL_CONFIG_H +#include <stl_config.h> +#endif +#ifndef __SGI_STL_INTERNAL_RELOPS +#include <stl_relops.h> +#endif +#ifndef __SGI_STL_INTERNAL_PAIR_H +#include <stl_pair.h> +#endif +#ifndef __TYPE_TRAITS_H_ +#include <type_traits.h> +#endif + +#include <string.h> +#include <limits.h> +#include <stdlib.h> +#include <stddef.h> +#include <new.h> +#include <iostream.h> + +#ifndef __SGI_STL_INTERNAL_ITERATOR_H +#include <stl_iterator.h> +#endif + +__STL_BEGIN_NAMESPACE + +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; +} + +#ifndef __BORLANDC__ + +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 /* __BORLANDC__ */ + +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 OutputIterator> +inline OutputIterator __copy(InputIterator first, InputIterator last, + OutputIterator result, input_iterator_tag) +{ + for ( ; first != last; ++result, ++first) + *result = *first; + return result; +} + +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) { + typedef typename __type_traits<T>::has_trivial_assignment_operator t; + return __copy_t(first, last, result, t()); + } +}; + +template <class T> +struct __copy_dispatch<const T*, T*> +{ + T* operator()(const T* first, const T* last, T* result) { + typedef typename __type_traits<T>::has_trivial_assignment_operator t; + return __copy_t(first, last, result, t()); + } +}; + +#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) { + typedef typename __type_traits<T>::has_trivial_assignment_operator t; + return __copy_backward_t(first, last, result, t()); + } +}; + +template <class T> +struct __copy_backward_dispatch<const T*, T*> +{ + T* operator()(const T* first, const T* last, T* result) { + typedef typename __type_traits<T>::has_trivial_assignment_operator t; + return __copy_backward_t(first, last, result, t()); + } +}; + +#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> +pair<InputIterator, OutputIterator> __copy_n(InputIterator first, Size count, + OutputIterator result, + input_iterator_tag) { + for ( ; count > 0; --count, ++first, ++result) + *result = *first; + return pair<InputIterator, OutputIterator>(first, result); +} + +template <class RandomAccessIterator, class Size, class OutputIterator> +inline pair<RandomAccessIterator, OutputIterator> +__copy_n(RandomAccessIterator first, Size count, + OutputIterator result, + random_access_iterator_tag) { + RandomAccessIterator last = first + count; + return pair<RandomAccessIterator, OutputIterator>(last, + copy(first, last, result)); +} + +template <class InputIterator, class Size, class OutputIterator> +inline pair<InputIterator, 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 ptrdiff_t len1 = last1 - first1; + const ptrdiff_t len2 = last2 - first2; + const int result = memcmp(first1, first2, min(len1, len2)); + return result != 0 ? result : (len1 == len2 ? 0 : (len1 < len2 ? -1 : 1)); +} + +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 +} + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_INTERNAL_ALGOBASE_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_alloc.h b/libstdc++/stl/stl_alloc.h new file mode 100644 index 00000000000..a6d41437bd4 --- /dev/null +++ b/libstdc++/stl/stl_alloc.h @@ -0,0 +1,698 @@ +/* + * 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. + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_ALLOC_H +#define __SGI_STL_INTERNAL_ALLOC_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> +#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. + + extern "C" { + extern int __us_rsthread_malloc; + } + // The above is copied from malloc.h. Including <malloc.h> + // would be cleaner but fails with certain levels of standard + // conformance. +# 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 + +__STL_BEGIN_NAMESPACE + +#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 > (size_t) __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. +# ifndef _NOTHREADS + /*REFERENCED*/ + lock lock_instance; +# endif + 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 > (size_t) __MAX_BYTES) { + malloc_alloc::deallocate(p, n); + return; + } + my_free_list = free_list + FREELIST_INDEX(n); + // acquire lock +# ifndef _NOTHREADS + /*REFERENCED*/ + lock lock_instance; +# endif /* _NOTHREADS */ + 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. + } + } + end_free = 0; // In case of exception. + 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 > (size_t) __MAX_BYTES && new_sz > (size_t) __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 +__STL_END_NAMESPACE +#include <mutex.h> +#include <time.h> +__STL_BEGIN_NAMESPACE +// 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 + +__STL_END_NAMESPACE + +#undef __PRIVATE + +#endif /* __SGI_STL_INTERNAL_ALLOC_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_bvector.h b/libstdc++/stl/stl_bvector.h new file mode 100644 index 00000000000..db02251facd --- /dev/null +++ b/libstdc++/stl/stl_bvector.h @@ -0,0 +1,614 @@ +/* + * + * 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,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. + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_BVECTOR_H +#define __SGI_STL_INTERNAL_BVECTOR_H + +__STL_BEGIN_NAMESPACE + +static const int __WORD_BIT = int(CHAR_BIT*sizeof(unsigned int)); + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma set woff 1174 +#endif + +struct __bit_reference { + unsigned int* p; + unsigned int mask; + __bit_reference(unsigned int* x, unsigned int y) : p(x), mask(y) {} + +public: + __bit_reference() : p(0), mask(0) {} + operator bool() const { return !(!(*p & mask)); } + __bit_reference& operator=(bool x) { + if (x) + *p |= mask; + else + *p &= ~mask; + return *this; + } + __bit_reference& operator=(const __bit_reference& x) { return *this = bool(x); } + bool operator==(const __bit_reference& x) const { + return bool(*this) == bool(x); + } + bool operator<(const __bit_reference& x) const { + return bool(*this) < bool(x); + } + void flip() { *p ^= mask; } +}; + +inline void swap(__bit_reference x, __bit_reference y) { + bool tmp = x; + x = y; + y = tmp; +} + +struct __bit_iterator : public random_access_iterator<bool, ptrdiff_t> { + typedef __bit_reference reference; + typedef __bit_reference* pointer; + typedef __bit_iterator iterator; + + 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; + } + } + + __bit_iterator() : p(0), offset(0) {} + __bit_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 = (unsigned int) n + __WORD_BIT; + --p; + } else + offset = (unsigned int) 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); + } +}; + +struct __bit_const_iterator + : public random_access_iterator<bool, ptrdiff_t> +{ + typedef bool reference; + typedef bool const_reference; + typedef const bool* pointer; + typedef __bit_const_iterator const_iterator; + + 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; + } + } + + __bit_const_iterator() : p(0), offset(0) {} + __bit_const_iterator(unsigned int* x, unsigned int y) : p(x), offset(y) {} + __bit_const_iterator(const __bit_iterator& x) : p(x.p), offset(x.offset) {} + const_reference operator*() const { + return __bit_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 = (unsigned int) n + __WORD_BIT; + --p; + } else + offset = (unsigned int) 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); + } +}; + +// The next few lines are confusing. What we're doing is declaring a +// partial specialization of vector<T, Alloc> if we have the necessary +// compiler support. Otherwise, we define a class bit_vector which uses +// the default allocator. In either case, we typedef "data_allocator" +// appropriately. + +#if defined(__STL_CLASS_PARTIAL_SPECIALIZATION) && !defined(__STL_NEED_BOOL) +#define __SGI_STL_VECBOOL_TEMPLATE +#define __BVECTOR vector +#else +#undef __SGI_STL_VECBOOL_TEMPLATE +#define __BVECTOR bit_vector +#endif + +# ifdef __SGI_STL_VECBOOL_TEMPLATE + __STL_END_NAMESPACE +# include <stl_vector.h> + __STL_BEGIN_NAMESPACE +template<class Alloc> class vector<bool, Alloc> +# else /* __SGI_STL_VECBOOL_TEMPLATE */ +class bit_vector +# endif /* __SGI_STL_VECBOOL_TEMPLATE */ +{ +# ifdef __SGI_STL_VECBOOL_TEMPLATE + typedef simple_alloc<unsigned int, Alloc> data_allocator; +# else /* __SGI_STL_VECBOOL_TEMPLATE */ + typedef simple_alloc<unsigned int, alloc> data_allocator; +# endif /* __SGI_STL_VECBOOL_TEMPLATE */ +public: + typedef bool value_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef __bit_reference reference; + typedef bool const_reference; + typedef __bit_reference* pointer; + typedef const bool* const_pointer; + + typedef __bit_iterator iterator; + typedef __bit_const_iterator const_iterator; + +#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION + typedef reverse_iterator<const_iterator> const_reverse_iterator; + typedef reverse_iterator<iterator> reverse_iterator; +#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + 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; +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +protected: + 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 + difference_type(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 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 + difference_type(n)); + copy(first, last, position); + finish += difference_type(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 */ + +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() + difference_type(n)); + } + const_reference operator[](size_type n) const { + return *(begin() + difference_type(n)); + } + __BVECTOR() : start(iterator()), finish(iterator()), end_of_storage(0) {} + __BVECTOR(size_type n, bool value) { + initialize(n); + fill(start.p, end_of_storage, value ? ~0 : 0); + } + __BVECTOR(int n, bool value) { + initialize(n); + fill(start.p, end_of_storage, value ? ~0 : 0); + } + __BVECTOR(long n, bool value) { + initialize(n); + fill(start.p, end_of_storage, value ? ~0 : 0); + } + explicit __BVECTOR(size_type n) { + initialize(n); + fill(start.p, end_of_storage, 0); + } + __BVECTOR(const __BVECTOR& x) { + initialize(x.size()); + copy(x.begin(), x.end(), start); + } + +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + __BVECTOR(InputIterator first, InputIterator last) { + initialize_range(first, last, iterator_category(first)); + } +#else /* __STL_MEMBER_TEMPLATES */ + __BVECTOR(const_iterator first, const_iterator last) { + size_type n = 0; + distance(first, last, n); + initialize(n); + copy(first, last, start); + } + __BVECTOR(const bool* first, const bool* last) { + size_type n = 0; + distance(first, last, n); + initialize(n); + copy(first, last, start); + } +#endif /* __STL_MEMBER_TEMPLATES */ + + ~__BVECTOR() { deallocate(); } + __BVECTOR& operator=(const __BVECTOR& x) { + if (&x == this) return *this; + if (x.size() > capacity()) { + deallocate(); + initialize(x.size()); + } + copy(x.begin(), x.end(), begin()); + finish = begin() + difference_type(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(__BVECTOR& x) { + __STD::swap(start, x.start); + __STD::swap(finish, x.finish); + __STD::swap(end_of_storage, x.end_of_storage); + } + iterator insert(iterator position, bool x = bool()) { + difference_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 + difference_type(n)); + fill(position, position + difference_type(n), x); + finish += difference_type(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 + difference_type(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() + difference_type(new_size), end()); + else + insert(end(), new_size - size(), x); + } + void clear() { erase(begin(), end()); } +}; + +#ifdef __SGI_STL_VECBOOL_TEMPLATE + +typedef vector<bool, alloc> bit_vector; + +#else /* __SGI_STL_VECBOOL_TEMPLATE */ + +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()); +} + +#endif /* __SGI_STL_VECBOOL_TEMPLATE */ + +#undef __SGI_STL_VECBOOL_TEMPLATE +#undef __BVECTOR + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma reset woff 1174 +#endif + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_INTERNAL_BVECTOR_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_config.h b/libstdc++/stl/stl_config.h index 31e96cf7cd3..c6546667a93 100644 --- a/libstdc++/stl/stl_config.h +++ b/libstdc++/stl/stl_config.h @@ -28,35 +28,47 @@ # 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 __SGI_STL_NO_ARROW_OPERATOR if the compiler is unable +// (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 class templates. +// (6) Defines __STL_FUNCTION_TMPL_PARTIAL_ORDER if the compiler supports +// partial ordering of function templates (a.k.a partial specialization +// of function templates. +// (7) Defines __STL_EXPLICIT_FUNCTION_TMPL_ARGS if the compiler +// supports calling a function template by providing its template +// arguments explicitly. +// (8) Defines __STL_MEMBER_TEMPLATES if the compiler supports +// template members of classes. +// (9) Defines 'explicit' as a null macro if the compiler does not support +// the explicit keyword. +// (10) Defines __STL_LIMITED_DEFAULT_TEMPLATES if the compiler is +// unable to handle default template parameters that depend on +// previous template parameters. +// (11) Defines __STL_NON_TYPE_TMPL_PARAM_BUG if the compiler has +// trouble performing function template argument deduction for +// non-type template parameters. +// (12) Defines __SGI_STL_NO_ARROW_OPERATOR if the compiler is unable // to support the -> operator for iterators. -// (11) Defines __STL_USE_EXCEPTIONS if the compiler (in the current +// (13) Defines __STL_USE_EXCEPTIONS if the compiler (in the current // compilation mode) supports exceptions. -// (12) Defines __STL_SGI_THREADS if this is being compiled on an SGI +// (14) Define __STL_USE_NAMESPACES if we're putting the STL into a +// namespace. +// (15) 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. -// (13) Defines __STL_WIN32THREADS if this is being compiled on a +// (16) Defines __STL_WIN32THREADS if this is being compiled on a // WIN32 compiler in multithreaded mode. -// (14) Defines __stl_assert either as a test or as a null macro, +// (17) Define namespace-related macros (__STD, __STL_BEGIN_NAMESPACE, etc.) +// apropriately. +// (18) Define exception-related macros (__STL_TRY, __STL_UNWIND, etc.) +// appropriately. +// (19) 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__) @@ -78,6 +90,9 @@ # ifdef __EXCEPTIONS # define __STL_USE_EXCEPTIONS # endif +# if (_COMPILER_VERSION >= 721) && defined(_NAMESPACES) +# define __STL_USE_NAMESPACES +# endif # if !defined(_NOTHREADS) && !defined(_PTHREADS) # define __STL_SGI_THREADS # endif @@ -90,6 +105,8 @@ # define __STL_NEED_EXPLICIT # else # define __STL_CLASS_PARTIAL_SPECIALIZATION +# define __STL_FUNCTION_TMPL_PARTIAL_ORDER +# define __STL_EXPLICIT_FUNCTION_TMPL_ARGS # define __STL_MEMBER_TEMPLATES # endif # ifdef __EXCEPTIONS @@ -108,6 +125,7 @@ # define __STL_MEMBER_TEMPLATES # define __STL_CLASS_PARTIAL_SPECIALIZATION # define __STL_USE_EXCEPTIONS +# define __STL_USE_NAMESPACES # endif # if defined(_MSC_VER) @@ -150,17 +168,60 @@ 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_EXPLICIT_FUNCTION_TMPL_ARGS +# define __STL_NULL_TMPL_ARGS <> +# else +# define __STL_NULL_TMPL_ARGS +# endif + +# ifdef __STL_CLASS_PARTIAL_SPECIALIZATION +# define __STL_TEMPLATE_NULL template<> +# else +# define __STL_TEMPLATE_NULL +# endif + +// __STL_NO_NAMESPACES is a hook so that users can disable namespaces +// without having to edit library headers. +# if defined(__STL_USE_NAMESPACES) && !defined(__STL_NO_NAMESPACES) +# define __STD std +# define __STL_BEGIN_NAMESPACE namespace std { +# define __STL_END_NAMESPACE } +# define __STL_USE_NAMESPACE_FOR_RELOPS +# define __STL_BEGIN_RELOPS_NAMESPACE namespace std { +# define __STL_END_RELOPS_NAMESPACE } +# define __STD_RELOPS std +# else +# define __STD +# define __STL_BEGIN_NAMESPACE +# define __STL_END_NAMESPACE +# undef __STL_USE_NAMESPACE_FOR_RELOPS +# define __STL_BEGIN_RELOPS_NAMESPACE +# define __STL_END_RELOPS_NAMESPACE +# define __STD_RELOPS +# endif + +# ifdef __STL_USE_EXCEPTIONS +# define __STL_TRY try +# define __STL_CATCH_ALL catch(...) +# define __STL_RETHROW throw +# define __STL_NOTHROW throw() +# define __STL_UNWIND(action) catch(...) { action; throw; } +# else +# define __STL_TRY +# define __STL_CATCH_ALL if (false) +# define __STL_RETHROW +# define __STL_NOTHROW +# define __STL_UNWIND(action) # endif #ifdef __STL_ASSERTIONS @@ -173,3 +234,7 @@ #endif #endif /* __STL_CONFIG_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_construct.h b/libstdc++/stl/stl_construct.h new file mode 100644 index 00000000000..46876353da6 --- /dev/null +++ b/libstdc++/stl/stl_construct.h @@ -0,0 +1,78 @@ +/* + * + * 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,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. + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_CONSTRUCT_H +#define __SGI_STL_INTERNAL_CONSTRUCT_H + +#include <new.h> + +__STL_BEGIN_NAMESPACE + +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*) { + typedef typename __type_traits<T>::has_trivial_destructor trivial_destructor; + __destroy_aux(first, last, 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*) {} + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_INTERNAL_CONSTRUCT_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_deque.h b/libstdc++/stl/stl_deque.h new file mode 100644 index 00000000000..79d40082f76 --- /dev/null +++ b/libstdc++/stl/stl_deque.h @@ -0,0 +1,1335 @@ +/* + * + * 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. + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_DEQUE_H +#define __SGI_STL_INTERNAL_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. + */ + +__STL_BEGIN_NAMESPACE + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma set woff 1174 +#endif + +// 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, class Ptr, size_t BufSiz> +struct __deque_iterator { + typedef __deque_iterator<T, T&, T*, BufSiz> iterator; + typedef __deque_iterator<T, const 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, class Ptr> +struct __deque_iterator { + typedef __deque_iterator<T, T&, T*> iterator; + typedef __deque_iterator<T, const 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 Ptr pointer; + typedef Ref reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T** map_pointer; + + typedef __deque_iterator self; + + T* cur; + T* first; + T* last; + map_pointer node; + + __deque_iterator(T* 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) {} + + reference operator*() const { return *cur; } +#ifndef __SGI_STL_NO_ARROW_OPERATOR + pointer operator->() const { return &(operator*()); } +#endif /* __SGI_STL_NO_ARROW_OPERATOR */ + + difference_type operator-(const self& x) const { + return difference_type(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 < difference_type(buffer_size())) + cur += n; + else { + difference_type node_offset = + offset > 0 ? offset / difference_type(buffer_size()) + : -difference_type((-offset - 1) / buffer_size()) - 1; + set_node(node + node_offset); + cur = first + (offset - node_offset * difference_type(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; + } + + reference 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 + difference_type(buffer_size()); + } +}; + +#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION + +#ifndef __STL_NON_TYPE_TMPL_PARAM_BUG + +template <class T, class Ref, class Ptr, size_t BufSiz> +inline random_access_iterator_tag +iterator_category(const __deque_iterator<T, Ref, Ptr, BufSiz>&) { + return random_access_iterator_tag(); +} + +template <class T, class Ref, class Ptr, size_t BufSiz> +inline T* value_type(const __deque_iterator<T, Ref, Ptr, BufSiz>&) { + return 0; +} + +template <class T, class Ref, class Ptr, size_t BufSiz> +inline ptrdiff_t* distance_type(const __deque_iterator<T, Ref, Ptr, BufSiz>&) { + return 0; +} + +#else /* __STL_NON_TYPE_TMPL_PARAM_BUG */ + +template <class T, class Ref, class Ptr> +inline random_access_iterator_tag +iterator_category(const __deque_iterator<T, Ref, Ptr>&) { + return random_access_iterator_tag(); +} + +template <class T, class Ref, class Ptr> +inline T* value_type(const __deque_iterator<T, Ref, Ptr>&) { return 0; } + +template <class T, class Ref, class Ptr> +inline ptrdiff_t* distance_type(const __deque_iterator<T, Ref, Ptr>&) { + return 0; +} + +#endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */ + +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +// 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 const value_type* const_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<T, T&, T*, BufSiz> iterator; + typedef __deque_iterator<T, const T&, const T&, BufSiz> const_iterator; +#else /* __STL_NON_TYPE_TMPL_PARAM_BUG */ + typedef __deque_iterator<T, T&, T*> iterator; + typedef __deque_iterator<T, const T&, const T*> const_iterator; +#endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */ + +#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION + typedef reverse_iterator<const_iterator> const_reverse_iterator; + typedef reverse_iterator<iterator> reverse_iterator; +#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + 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; +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +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[difference_type(n)]; } + const_reference operator[](size_type n) const { + return start[difference_type(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()); + __STL_TRY { + uninitialized_copy(x.begin(), x.end(), start); + } + __STL_UNWIND(destroy_map_and_nodes()); + } + + 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); + __STL_TRY { + uninitialized_copy(first, last, start); + } + __STL_UNWIND(destroy_map_and_nodes()); + } + + deque(const_iterator first, const_iterator last) + : start(), finish(), map(0), map_size(0) + { + create_map_and_nodes(last - first); + __STL_TRY { + uninitialized_copy(first, last, start); + } + __STL_UNWIND(destroy_map_and_nodes()); + } + +#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() + difference_type(len); + copy(x.begin(), mid, start); + insert(finish, mid, x.end()); + } + } + return *this; + } + + void swap(deque& x) { + __STD::swap(start, x.start); + __STD::swap(finish, x.finish); + __STD::swap(map, x.map); + __STD::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 + iterator erase(iterator pos) { + iterator next = pos; + ++next; + difference_type index = pos - start; + if (index < size() >> 1) { + copy_backward(start, pos, next); + pop_front(); + } + else { + copy(next, finish, pos); + pop_back(); + } + return start + index; + } + + iterator 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); + +#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); + +#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 - difference_type(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 + difference_type(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); + __STL_TRY { + uninitialized_copy(first, last, new_start); + start = new_start; + } + __STL_UNWIND(destroy_nodes_at_front(new_start)); + } + else if (pos.cur == finish.cur) { + iterator new_finish = reserve_elements_at_back(n); + __STL_TRY { + uninitialized_copy(first, last, finish); + finish = new_finish; + } + __STL_UNWIND(destroy_nodes_at_back(new_finish)); + } + 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); + __STL_TRY { + uninitialized_copy(first, last, new_start); + start = new_start; + } + __STL_UNWIND(destroy_nodes_at_front(new_start)); + } + else if (pos.cur == finish.cur) { + iterator new_finish = reserve_elements_at_back(n); + __STL_TRY { + uninitialized_copy(first, last, finish); + finish = new_finish; + } + __STL_UNWIND(destroy_nodes_at_back(new_finish)); + } + 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>::erase(iterator first, iterator last) { + if (first == start && last == finish) { + clear(); + return finish; + } + 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; + } + return start + elems_before; + } +} + +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; + __STL_TRY { + 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; + __STL_TRY { + 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(*n, *n + 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); + __STL_TRY { + uninitialized_copy(first, last, start); + } + __STL_UNWIND(destroy_map_and_nodes()); +} + +#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(); + __STL_TRY { + construct(finish.cur, t_copy); + finish.set_node(finish.node + 1); + finish.cur = finish.first; + } + __STL_UNWIND(deallocate_node(*(finish.node + 1))); +} + +// 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(); + __STL_TRY { + 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); + __STL_TRY { + uninitialized_copy(first, last, new_start); + start = new_start; + } + __STL_UNWIND(destroy_nodes_at_front(new_start)); + } + else if (pos.cur == finish.cur) { + iterator new_finish = reserve_elements_at_back(n); + __STL_TRY { + uninitialized_copy(first, last, finish); + finish = new_finish; + } + __STL_UNWIND(destroy_nodes_at_back(new_finish)); + } + else + insert_aux(pos, first, last, n); +} + +#endif /* __STL_MEMBER_TEMPLATES */ + +template <class T, class Alloc, size_t BufSize> +typename 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; + __STL_TRY { + if (elems_before >= difference_type(n)) { + iterator start_n = start + difference_type(n); + uninitialized_copy(start, start_n, new_start); + start = new_start; + copy(start_n, pos, old_start); + fill(pos - difference_type(n), pos, x_copy); + } + else { + __uninitialized_copy_fill(start, pos, new_start, start, x_copy); + start = new_start; + fill(old_start, pos, x_copy); + } + } + __STL_UNWIND(destroy_nodes_at_front(new_start)); + } + else { + iterator new_finish = reserve_elements_at_back(n); + iterator old_finish = finish; + const difference_type elems_after = difference_type(length) - elems_before; + pos = finish - elems_after; + __STL_TRY { + if (elems_after > difference_type(n)) { + iterator finish_n = finish - difference_type(n); + uninitialized_copy(finish_n, finish, finish); + finish = new_finish; + copy_backward(pos, finish_n, old_finish); + fill(pos, pos + difference_type(n), x_copy); + } + else { + __uninitialized_fill_copy(finish, pos + difference_type(n), + x_copy, + pos, finish); + finish = new_finish; + fill(pos, old_finish, x_copy); + } + } + __STL_UNWIND(destroy_nodes_at_back(new_finish)); + } +} + +#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; + __STL_TRY { + if (elems_before >= difference_type(n)) { + iterator start_n = start + difference_type(n); + uninitialized_copy(start, start_n, new_start); + start = new_start; + copy(start_n, pos, old_start); + copy(first, last, pos - difference_type(n)); + } + else { + ForwardIterator mid = first; + advance(mid, difference_type(n) - elems_before); + __uninitialized_copy_copy(start, pos, first, mid, new_start); + start = new_start; + copy(mid, last, old_start); + } + } + __STL_UNWIND(destroy_nodes_at_front(new_start)); + } + else { + iterator new_finish = reserve_elements_at_back(n); + iterator old_finish = finish; + const difference_type elems_after = difference_type(length) - elems_before; + pos = finish - elems_after; + __STL_TRY { + if (elems_after > difference_type(n)) { + iterator finish_n = finish - difference_type(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); + } + } + __STL_UNWIND(destroy_nodes_at_back(new_finish)); + } +} + +#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; + __STL_TRY { + if (elems_before >= difference_type(n)) { + iterator start_n = start + difference_type(n); + uninitialized_copy(start, start_n, new_start); + start = new_start; + copy(start_n, pos, old_start); + copy(first, last, pos - difference_type(n)); + } + else { + const value_type* mid = first + (difference_type(n) - elems_before); + __uninitialized_copy_copy(start, pos, first, mid, new_start); + start = new_start; + copy(mid, last, old_start); + } + } + __STL_UNWIND(destroy_nodes_at_front(new_start)); + } + else { + iterator new_finish = reserve_elements_at_back(n); + iterator old_finish = finish; + const difference_type elems_after = difference_type(length) - elems_before; + pos = finish - elems_after; + __STL_TRY { + if (elems_after > difference_type(n)) { + iterator finish_n = finish - difference_type(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); + } + } + __STL_UNWIND(destroy_nodes_at_back(new_finish)); + } +} + +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; + __STL_TRY { + 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 - difference_type(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); + } + } + __STL_UNWIND(destroy_nodes_at_front(new_start)); + } + 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; + __STL_TRY { + if (elems_after > n) { + iterator finish_n = finish - difference_type(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); + } + } + __STL_UNWIND(destroy_nodes_at_back(new_finish)); + } +} + +#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; + __STL_TRY { + 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; + __STL_TRY { + 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 */ + +#if defined(__STL_FUNCTION_TMPL_PARTIAL_ORDER) && \ + !defined(__STL_NON_TYPE_TMPL_PARAM_BUG) + +template <class T, class Alloc, size_t BufSiz> +inline void swap(deque<T, Alloc, BufSiz>& x, deque<T, Alloc, BufSiz>& y) { + x.swap(y); +} + +#endif + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma reset woff 1174 +#endif + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_INTERNAL_DEQUE_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_function.h b/libstdc++/stl/stl_function.h new file mode 100644 index 00000000000..c0d785d6a60 --- /dev/null +++ b/libstdc++/stl/stl_function.h @@ -0,0 +1,628 @@ +/* + * + * 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. + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_FUNCTION_H +#define __SGI_STL_INTERNAL_FUNCTION_H + +__STL_BEGIN_NAMESPACE + +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 typename Predicate::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 typename Predicate::first_argument_type& x, + const typename Predicate::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) {} + typename Operation::result_type + operator()(const typename Operation::second_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) {} + typename Operation::result_type + operator()(const typename Operation::first_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) {} + typename Operation1::result_type + operator()(const typename Operation2::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) { } + typename Operation1::result_type + operator()(const typename Operation2::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 val; + constant_unary_fun(const Result& v) : val(v) {} + const Result& operator()(const Argument&) 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 val; + constant_binary_fun(const Result& v) : val(v) {} + const Result& operator()(const Arg1&, const Arg2&) 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); +} + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_INTERNAL_FUNCTION_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_hash_fun.h b/libstdc++/stl/stl_hash_fun.h new file mode 100644 index 00000000000..3afa9dc554d --- /dev/null +++ b/libstdc++/stl/stl_hash_fun.h @@ -0,0 +1,93 @@ +/* + * 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. + * + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_HASH_FUN_H +#define __SGI_STL_HASH_FUN_H + +#include <stddef.h> + +__STL_BEGIN_NAMESPACE + +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); +} + +__STL_TEMPLATE_NULL struct hash<char*> +{ + size_t operator()(const char* s) const { return __stl_hash_string(s); } +}; + +__STL_TEMPLATE_NULL struct hash<const char*> +{ + size_t operator()(const char* s) const { return __stl_hash_string(s); } +}; + +__STL_TEMPLATE_NULL struct hash<char> { + size_t operator()(char x) const { return x; } +}; +__STL_TEMPLATE_NULL struct hash<unsigned char> { + size_t operator()(unsigned char x) const { return x; } +}; +__STL_TEMPLATE_NULL struct hash<signed char> { + size_t operator()(unsigned char x) const { return x; } +}; +__STL_TEMPLATE_NULL struct hash<short> { + size_t operator()(short x) const { return x; } +}; +__STL_TEMPLATE_NULL struct hash<unsigned short> { + size_t operator()(unsigned short x) const { return x; } +}; +__STL_TEMPLATE_NULL struct hash<int> { + size_t operator()(int x) const { return x; } +}; +__STL_TEMPLATE_NULL struct hash<unsigned int> { + size_t operator()(unsigned int x) const { return x; } +}; +__STL_TEMPLATE_NULL struct hash<long> { + size_t operator()(long x) const { return x; } +}; +__STL_TEMPLATE_NULL struct hash<unsigned long> { + size_t operator()(unsigned long x) const { return x; } +}; + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_HASH_FUN_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_hash_map.h b/libstdc++/stl/stl_hash_map.h new file mode 100644 index 00000000000..9999e9a401b --- /dev/null +++ b/libstdc++/stl/stl_hash_map.h @@ -0,0 +1,358 @@ +/* + * 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. + * + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_HASH_MAP_H +#define __SGI_STL_INTERNAL_HASH_MAP_H + + +__STL_BEGIN_NAMESPACE + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma set woff 1174 +#endif + +#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 typename ht::key_type key_type; + typedef T data_type; + typedef T mapped_type; + typedef typename ht::value_type value_type; + typedef typename ht::hasher hasher; + typedef typename ht::key_equal key_equal; + + typedef typename ht::size_type size_type; + typedef typename ht::difference_type difference_type; + typedef typename ht::pointer pointer; + typedef typename ht::const_pointer const_pointer; + typedef typename ht::reference reference; + typedef typename ht::const_reference const_reference; + + typedef typename ht::iterator iterator; + typedef typename 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== __STL_NULL_TMPL_ARGS (const hash_map&, const hash_map&); + + 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; +} + +#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER + +template <class Key, class T, class HashFcn, class EqualKey, class Alloc> +inline void swap(hash_map<Key, T, HashFcn, EqualKey, Alloc>& hm1, + hash_map<Key, T, HashFcn, EqualKey, Alloc>& hm2) +{ + hm1.swap(hm2); +} + +#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */ + +#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 typename ht::key_type key_type; + typedef T data_type; + typedef T mapped_type; + typedef typename ht::value_type value_type; + typedef typename ht::hasher hasher; + typedef typename ht::key_equal key_equal; + + typedef typename ht::size_type size_type; + typedef typename ht::difference_type difference_type; + typedef typename ht::pointer pointer; + typedef typename ht::const_pointer const_pointer; + typedef typename ht::reference reference; + typedef typename ht::const_reference const_reference; + + typedef typename ht::iterator iterator; + typedef typename 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== __STL_NULL_TMPL_ARGS (const hash_multimap&, const hash_multimap&); + + 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; +} + +#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER + +template <class Key, class T, class HashFcn, class EqualKey, class Alloc> +inline void swap(hash_multimap<Key, T, HashFcn, EqualKey, Alloc>& hm1, + hash_multimap<Key, T, HashFcn, EqualKey, Alloc>& hm2) +{ + hm1.swap(hm2); +} + +#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */ + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma reset woff 1174 +#endif + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_INTERNAL_HASH_MAP_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_hash_set.h b/libstdc++/stl/stl_hash_set.h new file mode 100644 index 00000000000..80159dab59f --- /dev/null +++ b/libstdc++/stl/stl_hash_set.h @@ -0,0 +1,342 @@ +/* + * 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. + * + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_HASH_SET_H +#define __SGI_STL_INTERNAL_HASH_SET_H + +__STL_BEGIN_NAMESPACE + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma set woff 1174 +#endif + +#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 typename ht::key_type key_type; + typedef typename ht::value_type value_type; + typedef typename ht::hasher hasher; + typedef typename ht::key_equal key_equal; + + typedef typename ht::size_type size_type; + typedef typename ht::difference_type difference_type; + typedef typename ht::const_pointer pointer; + typedef typename ht::const_pointer const_pointer; + typedef typename ht::const_reference reference; + typedef typename ht::const_reference const_reference; + + typedef typename ht::const_iterator iterator; + typedef typename 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== __STL_NULL_TMPL_ARGS (const hash_set&, + const hash_set&); + + iterator begin() const { return rep.begin(); } + iterator end() const { return rep.end(); } + +public: + pair<iterator, bool> insert(const value_type& obj) + { + pair<typename 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<typename 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; +} + +#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER + +template <class Val, class HashFcn, class EqualKey, class Alloc> +inline void swap(hash_set<Val, HashFcn, EqualKey, Alloc>& hs1, + hash_set<Val, HashFcn, EqualKey, Alloc>& hs2) { + hs1.swap(hs2); +} + +#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */ + + +#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 typename ht::key_type key_type; + typedef typename ht::value_type value_type; + typedef typename ht::hasher hasher; + typedef typename ht::key_equal key_equal; + + typedef typename ht::size_type size_type; + typedef typename ht::difference_type difference_type; + typedef typename ht::const_pointer pointer; + typedef typename ht::const_pointer const_pointer; + typedef typename ht::const_reference reference; + typedef typename ht::const_reference const_reference; + + typedef typename ht::const_iterator iterator; + typedef typename 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== __STL_NULL_TMPL_ARGS (const hash_multiset&, + const hash_multiset&); + + 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; +} + +#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER + +template <class Val, class HashFcn, class EqualKey, class Alloc> +inline void swap(hash_multiset<Val, HashFcn, EqualKey, Alloc>& hs1, + hash_multiset<Val, HashFcn, EqualKey, Alloc>& hs2) + hs1.swap(hs2); +} + +#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */ + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma reset woff 1174 +#endif + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_INTERNAL_HASH_SET_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_hashtable.h b/libstdc++/stl/stl_hashtable.h new file mode 100644 index 00000000000..2452f625d3d --- /dev/null +++ b/libstdc++/stl/stl_hashtable.h @@ -0,0 +1,948 @@ +/* + * 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. + * + * + * 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. + * + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_HASHTABLE_H +#define __SGI_STL_INTERNAL_HASHTABLE_H + +// Hashtable class, used to implement the hashed associative containers +// hash_set, hash_map, hash_multiset, and hash_multimap. + +#include <stl_algobase.h> +#include <stl_alloc.h> +#include <stl_construct.h> +#include <stl_tempbuf.h> +#include <stl_algo.h> +#include <stl_uninitialized.h> +#include <stl_function.h> +#include <stl_vector.h> +#include <stl_hash_fun.h> + +__STL_BEGIN_NAMESPACE + +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 Value* pointer; + + node* cur; + hashtable* ht; + + __hashtable_iterator(node* n, hashtable* tab) : cur(n), ht(tab) {} + __hashtable_iterator() {} + reference operator*() const { return cur->val; } +#ifndef __SGI_STL_NO_ARROW_OPERATOR + pointer operator->() const { return &(operator*()); } +#endif /* __SGI_STL_NO_ARROW_OPERATOR */ + 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 const Value& reference; + typedef const 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) {} + reference operator*() const { return cur->val; } +#ifndef __SGI_STL_NO_ARROW_OPERATOR + pointer operator->() const { return &(operator*()); } +#endif /* __SGI_STL_NO_ARROW_OPERATOR */ + 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) + { + __STD::swap(hash, ht.hash); + __STD::swap(equals, ht.equals); + __STD::swap(get_key, ht.get_key); + buckets.swap(ht.buckets); + __STD::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== __STL_NULL_TMPL_ARGS (const hashtable&, const hashtable&); + +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); + } + +#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; + __STL_TRY { + construct(&n->val, obj); + return n; + } + __STL_UNWIND(node_allocator::deallocate(n)); + } + + 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; +} + +#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION + +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; +} + +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +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 typename 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; +} + +#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER + +template <class Val, class Key, class HF, class Extract, class EqKey, class A> +inline void swap(hashtable<Val, Key, HF, Extract, EqKey, A>& ht1, + hashtable<Val, Key, HF, Extract, EqKay, A>& ht2) { + ht1.swap(ht2); +} + +#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */ + + +template <class V, class K, class HF, class Ex, class Eq, class A> +pair<typename 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> +typename 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> +typename 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<typename hashtable<V, K, HF, Ex, Eq, A>::iterator, + typename 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<typename hashtable<V, K, HF, Ex, Eq, A>::const_iterator, + typename 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> +typename 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<node*>(first.cur), + const_cast<hashtable*>(first.ht)), + iterator(const_cast<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<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); + __STL_TRY { + 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); + __STL_TRY { + 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; + } + __STL_UNWIND(clear()); +} + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_INTERNAL_HASHTABLE_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_heap.h b/libstdc++/stl/stl_heap.h new file mode 100644 index 00000000000..3fe24f833fc --- /dev/null +++ b/libstdc++/stl/stl_heap.h @@ -0,0 +1,226 @@ +/* + * + * 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. + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_HEAP_H +#define __SGI_STL_INTERNAL_HEAP_H + +__STL_BEGIN_NAMESPACE + +#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 + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_INTERNAL_HEAP_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_iterator.h b/libstdc++/stl/stl_iterator.h new file mode 100644 index 00000000000..892db3e3dbb --- /dev/null +++ b/libstdc++/stl/stl_iterator.h @@ -0,0 +1,843 @@ +/* + * + * 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,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. + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_ITERATOR_H +#define __SGI_STL_INTERNAL_ITERATOR_H + +__STL_BEGIN_NAMESPACE + +struct input_iterator_tag {}; +struct output_iterator_tag {}; +struct forward_iterator_tag : public input_iterator_tag {}; +struct bidirectional_iterator_tag : public forward_iterator_tag {}; +struct random_access_iterator_tag : public bidirectional_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; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; +}; + +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; +}; + +#ifdef __STL_USE_NAMESPACES +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 /* __STL_USE_NAMESPACES */ + +#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; +}; + +template <class T> +struct iterator_traits<const T*> { + typedef random_access_iterator_tag iterator_category; + typedef T value_type; + typedef ptrdiff_t difference_type; + typedef const T* pointer; + typedef const T& reference; +}; + +template <class Iterator> +inline typename iterator_traits<Iterator>::iterator_category +iterator_category(const Iterator&) { + typedef typename iterator_traits<Iterator>::iterator_category category; + return category(); +} + +template <class Iterator> +inline typename iterator_traits<Iterator>::difference_type* +distance_type(const Iterator&) { + return static_cast<typename iterator_traits<Iterator>::difference_type*>(0); +} + +template <class Iterator> +inline typename iterator_traits<Iterator>::value_type* +value_type(const Iterator&) { + return static_cast<typename iterator_traits<Iterator>::value_type*>(0); +} + +#else /* __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); } + +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +template <class InputIterator, class Distance> +inline void __distance(InputIterator first, InputIterator last, Distance& n, + input_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 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) { + typedef typename iterator_traits<InputIterator>::iterator_category category; + return __distance(first, last, category()); +} + +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +template <class InputIterator, class Distance> +inline void __advance(InputIterator& i, Distance n, input_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 Container> +class back_insert_iterator { +protected: + Container* container; +public: + typedef output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + 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; } +}; + +#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION + +template <class Container> +inline output_iterator_tag +iterator_category(const back_insert_iterator<Container>&) +{ + return output_iterator_tag(); +} + +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +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; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + 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; } +}; + +#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION + +template <class Container> +inline output_iterator_tag +iterator_category(const front_insert_iterator<Container>&) +{ + return output_iterator_tag(); +} + +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +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; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + 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; } +}; + +#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION + +template <class Container> +inline output_iterator_tag +iterator_category(const insert_iterator<Container>&) +{ + return output_iterator_tag(); +} + +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +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; +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() const { return current; } + Reference operator*() const { + BidirectionalIterator tmp = current; + return *--tmp; + } +#ifndef __SGI_STL_NO_ARROW_OPERATOR + pointer operator->() const { return &(operator*()); } +#endif /* __SGI_STL_NO_ARROW_OPERATOR */ + 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; + } +}; + +#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION + +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; +} + +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +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.base() == y.base(); +} + +#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION + +// This is the new version of reverse_iterator, as defined in the +// draft C++ standard. It relies on the iterator_traits template, +// which in turn relies on partial specialization. The class +// reverse_bidirectional_iterator is no longer part of the draft +// standard, but it is retained for backward compatibility. + +template <class Iterator> +class reverse_iterator +{ +protected: + Iterator current; +public: + typedef typename iterator_traits<Iterator>::iterator_category + iterator_category; + typedef typename iterator_traits<Iterator>::value_type + value_type; + typedef typename iterator_traits<Iterator>::difference_type + difference_type; + typedef typename iterator_traits<Iterator>::pointer + pointer; + typedef typename iterator_traits<Iterator>::reference + reference; + + typedef Iterator iterator_type; + typedef reverse_iterator<Iterator> self; + +public: + reverse_iterator() {} + explicit reverse_iterator(iterator_type x) : current(x) {} + + reverse_iterator(const self& x) : current(x.current) {} +#ifdef __STL_MEMBER_TEMPLATES + template <class Iter> + reverse_iterator(const reverse_iterator<Iter>& x) : current(x.current) {} +#endif /* __STL_MEMBER_TEMPLATES */ + + iterator_type base() const { return current; } + reference operator*() const { + Iterator tmp = current; + return *--tmp; + } +#ifndef __SGI_STL_NO_ARROW_OPERATOR + pointer operator->() const { return &(operator*()); } +#endif /* __SGI_STL_NO_ARROW_OPERATOR */ + + 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+(difference_type n) const { + return self(current - n); + } + self& operator+=(difference_type n) { + current -= n; + return *this; + } + self operator-(difference_type n) const { + return self(current + n); + } + self& operator-=(difference_type n) { + current += n; + return *this; + } + reference operator[](difference_type n) const { return *(*this + n); } +}; + +template <class Iterator> +inline bool operator==(const reverse_iterator<Iterator>& x, + const reverse_iterator<Iterator>& y) { + return x.base() == y.base(); +} + +template <class Iterator> +inline bool operator<(const reverse_iterator<Iterator>& x, + const reverse_iterator<Iterator>& y) { + return y.base() < x.base(); +} + +template <class Iterator> +inline typename reverse_iterator<Iterator>::difference_type +operator-(const reverse_iterator<Iterator>& x, + const reverse_iterator<Iterator>& y) { + return y.base() - x.base(); +} + +template <class Iterator> +inline reverse_iterator<Iterator> +operator+(reverse_iterator<Iterator>::difference_type n, + const reverse_iterator<Iterator>& x) { + return reverse_iterator<Iterator>(x.base() - n); +} + +#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +// This is the old version of reverse_iterator, as found in the original +// HP STL. It does not use partial specialization. + +#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; +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() const { return current; } + Reference operator*() const { return *(current - 1); } +#ifndef __SGI_STL_NO_ARROW_OPERATOR + pointer operator->() const { return &(operator*()); } +#endif /* __SGI_STL_NO_ARROW_OPERATOR */ + 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) const { 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.base() == y.base(); +} + +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.base() < x.base(); +} + +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.base() - x.base(); +} + +template <class RandomAccessIter, class T, class Ref, class Dist> +inline reverse_iterator<RandomAccessIter, T, Ref, Dist> +operator+(Dist n, const reverse_iterator<RandomAccessIter, T, Ref, Dist>& x) { + return reverse_iterator<RandomAccessIter, T, Ref, Dist>(x.base() - n); +} + +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +template <class T, class Distance = ptrdiff_t> +class istream_iterator { + friend bool + operator== __STL_NULL_TMPL_ARGS (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 const T* pointer; + typedef const T& reference; + + istream_iterator() : stream(&cin), end_marker(false) {} + istream_iterator(istream& s) : stream(&s) { read(); } + reference operator*() const { return value; } +#ifndef __SGI_STL_NO_ARROW_OPERATOR + pointer operator->() const { return &(operator*()); } +#endif /* __SGI_STL_NO_ARROW_OPERATOR */ + istream_iterator<T, Distance>& operator++() { + read(); + return *this; + } + istream_iterator<T, Distance> operator++(int) { + istream_iterator<T, Distance> tmp = *this; + read(); + return tmp; + } +}; + +#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION + +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; +} + +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +template <class T, class Distance> +inline 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; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + 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; } +}; + +#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION + +template <class T> +inline output_iterator_tag +iterator_category(const ostream_iterator<T>&) { + return output_iterator_tag(); +} + +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_INTERNAL_ITERATOR_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_list.h b/libstdc++/stl/stl_list.h new file mode 100644 index 00000000000..ac836b6fcf9 --- /dev/null +++ b/libstdc++/stl/stl_list.h @@ -0,0 +1,617 @@ +/* + * + * 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,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. + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_LIST_H +#define __SGI_STL_INTERNAL_LIST_H + +__STL_BEGIN_NAMESPACE + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma set woff 1174 +#endif + +template <class T> +struct __list_node { + typedef void* void_pointer; + void_pointer next; + void_pointer prev; + T data; +}; + +template<class T, class Ref, class Ptr> +struct __list_iterator { + typedef __list_iterator<T, T&, T*> iterator; + typedef __list_iterator<T, const T&, const T*> const_iterator; + typedef __list_iterator<T, Ref, Ptr> self; + + typedef bidirectional_iterator_tag iterator_category; + typedef T value_type; + typedef Ptr pointer; + typedef Ref 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; } + reference operator*() const { return (*node).data; } + +#ifndef __SGI_STL_NO_ARROW_OPERATOR + pointer operator->() const { return &(operator*()); } +#endif /* __SGI_STL_NO_ARROW_OPERATOR */ + + 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; + } +}; + +#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION + +template <class T, class Ref, class Ptr> +inline bidirectional_iterator_tag +iterator_category(const __list_iterator<T, Ref, Ptr>&) { + return bidirectional_iterator_tag(); +} + +template <class T, class Ref, class Ptr> +inline T* +value_type(const __list_iterator<T, Ref, Ptr>&) { + return 0; +} + +template <class T, class Ref, class Ptr> +inline ptrdiff_t* +distance_type(const __list_iterator<T, Ref, Ptr>&) { + return 0; +} + +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +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 const value_type* const_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&, T*> iterator; + typedef __list_iterator<T, const T&, const T*> const_iterator; + +#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION + typedef reverse_iterator<const_iterator> const_reverse_iterator; + typedef reverse_iterator<iterator> reverse_iterator; +#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + 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; +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +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(); + __STL_TRY { + construct(&p->data, x); + } + __STL_UNWIND(put_node(p)); + return p; + } + 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(); + __STL_TRY { + insert(begin(), n, value); + } + __STL_UNWIND(clear(); put_node(node)); + } + +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + void range_initialize(InputIterator first, InputIterator last) { + empty_initialize(); + __STL_TRY { + insert(begin(), first, last); + } + __STL_UNWIND(clear(); put_node(node)); + } +#else /* __STL_MEMBER_TEMPLATES */ + void range_initialize(const T* first, const T* last) { + empty_initialize(); + __STL_TRY { + insert(begin(), first, last); + } + __STL_UNWIND(clear(); put_node(node)); + } + void range_initialize(const_iterator first, const_iterator last) { + empty_initialize(); + __STL_TRY { + insert(begin(), first, last); + } + __STL_UNWIND(clear(); put_node(node)); + } +#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) { __STD::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); } + iterator erase(iterator position) { + link_type next_node = link_type(position.node->next); + link_type prev_node = link_type(position.node->prev); + prev_node->next = next_node; + next_node->prev = prev_node; + destroy_node(position.node); + return iterator(next_node); + } + iterator 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== __STL_NULL_TMPL_ARGS (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 typename 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_FUNCTION_TMPL_PARTIAL_ORDER + +template <class T, class Alloc> +inline void swap(list<T, Alloc>& x, list<T, Alloc>& y) { + x.swap(y); +} + +#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */ + +#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> +list<T,Alloc>::iterator list<T, Alloc>::erase(iterator first, iterator last) { + while (first != last) erase(first++); + return last; +} + +template <class T, class Alloc> +void list<T, Alloc>::resize(size_type new_size, const T& x) +{ + iterator i = begin(); + size_type len = 0; + for ( ; i != end() && len < new_size; ++i, ++len) + ; + if (len == new_size) + erase(i, end()); + else // i == end() + 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 */ + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma reset woff 1174 +#endif + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_INTERNAL_LIST_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_map.h b/libstdc++/stl/stl_map.h new file mode 100644 index 00000000000..2a830cc65f2 --- /dev/null +++ b/libstdc++/stl/stl_map.h @@ -0,0 +1,217 @@ +/* + * + * 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,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. + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_MAP_H +#define __SGI_STL_INTERNAL_MAP_H + +__STL_BEGIN_NAMESPACE + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma set woff 1174 +#endif + +#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 T mapped_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 typename rep_type::pointer pointer; + typedef typename rep_type::const_pointer const_pointer; + typedef typename rep_type::reference reference; + typedef typename rep_type::const_reference const_reference; + typedef typename rep_type::iterator iterator; + typedef typename rep_type::const_iterator const_iterator; + typedef typename rep_type::reverse_iterator reverse_iterator; + typedef typename rep_type::const_reverse_iterator const_reverse_iterator; + typedef typename rep_type::size_type size_type; + typedef typename 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== __STL_NULL_TMPL_ARGS (const map&, const map&); + friend bool operator< __STL_NULL_TMPL_ARGS (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; +} + +#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER + +template <class Key, class T, class Compare, class Alloc> +inline void swap(map<Key, T, Compare, Alloc>& x, + map<Key, T, Compare, Alloc>& y) { + x.swap(y); +} + +#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */ + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma reset woff 1174 +#endif + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_INTERNAL_MAP_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_multimap.h b/libstdc++/stl/stl_multimap.h new file mode 100644 index 00000000000..b82159b648e --- /dev/null +++ b/libstdc++/stl/stl_multimap.h @@ -0,0 +1,214 @@ +/* + * + * 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,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. + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_MULTIMAP_H +#define __SGI_STL_INTERNAL_MULTIMAP_H + +__STL_BEGIN_NAMESPACE + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma set woff 1174 +#endif + +#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 T mapped_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 typename rep_type::pointer pointer; + typedef typename rep_type::const_pointer const_pointer; + typedef typename rep_type::reference reference; + typedef typename rep_type::const_reference const_reference; + typedef typename rep_type::iterator iterator; + typedef typename rep_type::const_iterator const_iterator; + typedef typename rep_type::reverse_iterator reverse_iterator; + typedef typename rep_type::const_reverse_iterator const_reverse_iterator; + typedef typename rep_type::size_type size_type; + typedef typename 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== __STL_NULL_TMPL_ARGS (const multimap&, + const multimap&); + friend bool operator< __STL_NULL_TMPL_ARGS (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; +} + +#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER + +template <class Key, class T, class Compare, class Alloc> +inline void swap(multimap<Key, T, Compare, Alloc>& x, + multimap<Key, T, Compare, Alloc>& y) { + x.swap(y); +} + +#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */ + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma reset woff 1174 +#endif + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_INTERNAL_MULTIMAP_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_multiset.h b/libstdc++/stl/stl_multiset.h new file mode 100644 index 00000000000..ff5947e1490 --- /dev/null +++ b/libstdc++/stl/stl_multiset.h @@ -0,0 +1,200 @@ +/* + * + * 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. + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_MULTISET_H +#define __SGI_STL_INTERNAL_MULTISET_H + +__STL_BEGIN_NAMESPACE + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma set woff 1174 +#endif + +#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 typename rep_type::const_pointer pointer; + typedef typename rep_type::const_pointer const_pointer; + typedef typename rep_type::const_reference reference; + typedef typename rep_type::const_reference const_reference; + typedef typename rep_type::const_iterator iterator; + typedef typename rep_type::const_iterator const_iterator; + typedef typename rep_type::const_reverse_iterator reverse_iterator; + typedef typename rep_type::const_reverse_iterator const_reverse_iterator; + typedef typename rep_type::size_type size_type; + typedef typename 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) { + typedef typename rep_type::iterator rep_iterator; + return t.insert_equal((rep_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) { + typedef typename rep_type::iterator rep_iterator; + t.erase((rep_iterator&)position); + } + size_type erase(const key_type& x) { + return t.erase(x); + } + void erase(iterator first, iterator last) { + typedef typename rep_type::iterator rep_iterator; + t.erase((rep_iterator&)first, (rep_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== __STL_NULL_TMPL_ARGS (const multiset&, + const multiset&); + friend bool operator< __STL_NULL_TMPL_ARGS (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; +} + +#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER + +template <class Key, class Compare, class Alloc> +inline void swap(multiset<Key, Compare, Alloc>& x, + multiset<Key, Compare, Alloc>& y) { + x.swap(y); +} + +#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */ + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma reset woff 1174 +#endif + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_INTERNAL_MULTISET_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_numeric.h b/libstdc++/stl/stl_numeric.h new file mode 100644 index 00000000000..57fee2b1b5c --- /dev/null +++ b/libstdc++/stl/stl_numeric.h @@ -0,0 +1,196 @@ +/* + * + * 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,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. + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + + +#ifndef __SGI_STL_INTERNAL_NUMERIC_H +#define __SGI_STL_INTERNAL_NUMERIC_H + +__STL_BEGIN_NAMESPACE + +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 & 1) == 0) { + n >>= 1; + x = op(x, x); + } + + T result = x; + n >>= 1; + while (n != 0) { + x = op(x, x); + if ((n & 1) != 0) + result = op(result, x); + n >>= 1; + } + 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++; +} + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_INTERNAL_NUMERIC_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_pair.h b/libstdc++/stl/stl_pair.h new file mode 100644 index 00000000000..10a9cb08e3b --- /dev/null +++ b/libstdc++/stl/stl_pair.h @@ -0,0 +1,73 @@ +/* + * + * 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,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. + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_PAIR_H +#define __SGI_STL_INTERNAL_PAIR_H + +__STL_BEGIN_NAMESPACE + +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); +} + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_INTERNAL_PAIR_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_queue.h b/libstdc++/stl/stl_queue.h new file mode 100644 index 00000000000..ff6eedeb701 --- /dev/null +++ b/libstdc++/stl/stl_queue.h @@ -0,0 +1,134 @@ +/* + * + * 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,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. + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_QUEUE_H +#define __SGI_STL_INTERNAL_QUEUE_H + +__STL_BEGIN_NAMESPACE + +#ifndef __STL_LIMITED_DEFAULT_TEMPLATES +template <class T, class Sequence = deque<T> > +#else +template <class T, class Sequence> +#endif +class queue { + friend bool operator== __STL_NULL_TMPL_ARGS (const queue& x, const queue& y); + friend bool operator< __STL_NULL_TMPL_ARGS (const queue& x, const queue& y); +public: + typedef typename Sequence::value_type value_type; + typedef typename Sequence::size_type size_type; + typedef typename Sequence::reference reference; + typedef typename Sequence::const_reference const_reference; +protected: + Sequence c; +public: + bool empty() const { return c.empty(); } + size_type size() const { return c.size(); } + reference front() { return c.front(); } + const_reference front() const { return c.front(); } + reference back() { return c.back(); } + const_reference 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; + typedef typename Sequence::reference reference; + typedef typename Sequence::const_reference const_reference; +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_reference top() const { return c.front(); } + void push(const value_type& x) { + __STL_TRY { + c.push_back(x); + push_heap(c.begin(), c.end(), comp); + } + __STL_UNWIND(c.clear()); + } + void pop() { + __STL_TRY { + pop_heap(c.begin(), c.end(), comp); + c.pop_back(); + } + __STL_UNWIND(c.clear()); + } +}; + +// no equality is provided + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_INTERNAL_QUEUE_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_raw_storage_iter.h b/libstdc++/stl/stl_raw_storage_iter.h new file mode 100644 index 00000000000..5d3d0747b5e --- /dev/null +++ b/libstdc++/stl/stl_raw_storage_iter.h @@ -0,0 +1,81 @@ +/* + * + * 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. + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_RAW_STORAGE_ITERATOR_H +#define __SGI_STL_INTERNAL_RAW_STORAGE_ITERATOR_H + +__STL_BEGIN_NAMESPACE + +template <class ForwardIterator, class T> +class raw_storage_iterator { +protected: + ForwardIterator iter; +public: + typedef output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + 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; + } +}; + +#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION + +template <class ForwardIterator, class T> +inline output_iterator_tag +iterator_category(const raw_storage_iterator<ForwardIterator, T>&) +{ + return output_iterator_tag(); +} + +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +#endif /* __SGI_STL_INTERNAL_RAW_STORAGE_ITERATOR_H */ + +__STL_END_NAMESPACE + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_relops.h b/libstdc++/stl/stl_relops.h new file mode 100644 index 00000000000..01a0c7cdfcb --- /dev/null +++ b/libstdc++/stl/stl_relops.h @@ -0,0 +1,62 @@ +/* + * + * 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,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. + * + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_RELOPS +#define __SGI_STL_INTERNAL_RELOPS + +__STL_BEGIN_RELOPS_NAMESPACE + +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); +} + +__STL_END_RELOPS_NAMESPACE + +#endif /* __SGI_STL_INTERNAL_RELOPS */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_rope.h b/libstdc++/stl/stl_rope.h new file mode 100644 index 00000000000..620db6ffbc5 --- /dev/null +++ b/libstdc++/stl/stl_rope.h @@ -0,0 +1,2112 @@ +/* + * 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. + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_ROPE_H +# define __SGI_STL_INTERNAL_ROPE_H + +# ifdef __GC +# define __GC_CONST const +# else +# define __GC_CONST // constant except for deallocation +# endif +# ifdef __STL_SGI_THREADS +# include <mutex.h> +# endif + +__STL_BEGIN_NAMESPACE + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma set woff 1174 +#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 *) { return false; } +template <class charT> +inline bool __is_one_byte_char_type(charT *) { return false; } + +inline bool __is_basic_char_type(char *) { return true; } +inline bool __is_one_byte_char_type(char *) { return true; } +inline bool __is_basic_char_type(wchar_t *) { 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&) {} + +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<charT, Alloc> DataAlloc; + 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(); + } + static void free_if_unref(__rope_RopeBase* t) + { + if (0 != t && 0 == t -> refcount) t -> free_tree(); + } +# 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 *); + static void free_if_unref(__rope_RopeBase* t) {} +# 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; + } else { + size_with_eos = n; + } +# 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 + +// 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== __STL_NULL_TMPL_ARGS + (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. + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma set woff 1375 +#endif + +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: + typedef charT reference; // Really a value. Returning a reference + // Would be a mess, since it would have + // to be included in refcount. + typedef const charT* pointer; + + 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); + } + reference 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- __STL_NULL_TMPL_ARGS + (const __rope_const_iterator<charT,Alloc> & x, + ptrdiff_t n); + friend __rope_const_iterator<charT,Alloc> operator+ __STL_NULL_TMPL_ARGS + (const __rope_const_iterator<charT,Alloc> & x, + ptrdiff_t n); + friend __rope_const_iterator<charT,Alloc> operator+ __STL_NULL_TMPL_ARGS + (ptrdiff_t n, + const __rope_const_iterator<charT,Alloc> & x); + reference operator[](size_t n) { + return rope<charT,Alloc>::fetch(root, current_pos + n); + } + friend bool operator== __STL_NULL_TMPL_ARGS + (const __rope_const_iterator<charT,Alloc> & x, + const __rope_const_iterator<charT,Alloc> & y); + friend bool operator< __STL_NULL_TMPL_ARGS + (const __rope_const_iterator<charT,Alloc> & x, + const __rope_const_iterator<charT,Alloc> & y); + friend ptrdiff_t operator- __STL_NULL_TMPL_ARGS + (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: + typedef __rope_charT_ref_proxy<charT,Alloc> reference; + typedef __rope_charT_ref_proxy<charT,Alloc>* pointer; + + 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); + } + reference 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); + } + reference operator[](ptrdiff_t n) { + return __rope_charT_ref_proxy<charT,Alloc>(root_rope, current_pos + n); + } + friend bool operator== __STL_NULL_TMPL_ARGS + (const __rope_iterator<charT,Alloc> & x, + const __rope_iterator<charT,Alloc> & y); + friend bool operator< __STL_NULL_TMPL_ARGS + (const __rope_iterator<charT,Alloc> & x, + const __rope_iterator<charT,Alloc> & y); + friend ptrdiff_t operator- __STL_NULL_TMPL_ARGS + (const __rope_iterator<charT,Alloc> & x, + const __rope_iterator<charT,Alloc> & y); + friend __rope_iterator<charT,Alloc> operator- __STL_NULL_TMPL_ARGS + (const __rope_iterator<charT,Alloc> & x, + ptrdiff_t n); + friend __rope_iterator<charT,Alloc> operator+ __STL_NULL_TMPL_ARGS + (const __rope_iterator<charT,Alloc> & x, + ptrdiff_t n); + friend __rope_iterator<charT,Alloc> operator+ __STL_NULL_TMPL_ARGS + (ptrdiff_t n, + const __rope_iterator<charT,Alloc> & x); + +}; + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma reset woff 1375 +#endif + +template <class charT, class Alloc> +class rope { + public: + typedef charT value_type; + typedef ptrdiff_t difference_type; + typedef size_t size_type; + typedef 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<charT, Alloc> DataAlloc; + 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 = DataAlloc::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). + + static RopeLeaf * RopeLeaf_from_unowned_char_ptr(const charT *s, + size_t size) { + charT * buf = alloc_copy(s, size); + __STL_TRY { + return RopeLeaf_from_char_ptr(buf, size); + } + __STL_UNWIND(RopeBase::free_string(buf, 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 + : public binary_function<rope<charT,Alloc>, rope<charT,Alloc>, + rope<charT,Alloc> > { + rope operator() (const rope& x, const rope& y) { + return x + y; + } + }; + + friend rope identity_element(concat_fn) { return rope<charT,Alloc>(); } + + 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_unowned_char_ptr(s, 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_unowned_char_ptr(s, len); + } + } + + rope(const charT *s, charT *e) + { + size_t len = e - s; + + if (0 == len) { + tree_ptr = 0; + } else { + tree_ptr = RopeLeaf_from_unowned_char_ptr(s, 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 = DataAlloc::allocate(rounded_up_size(1)); + + construct(buf, c); + __STL_TRY { + tree_ptr = RopeLeaf_from_char_ptr(buf, 1); + } + __STL_UNWIND(RopeBase::free_string(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_unowned_char_ptr(i, 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(charT x) + { + RopeBase *old = tree_ptr; + RopeBase *left; + + left = RopeLeaf_from_unowned_char_ptr(&x, 1); + __STL_TRY { + tree_ptr = concat(left, tree_ptr); + unref(old); + unref(left); + } + __STL_UNWIND(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. + } + +# ifdef __STL_CLASS_PARTIAL_SPECIALIZATION + typedef reverse_iterator<const_iterator> const_reverse_iterator; +# else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + typedef reverse_iterator<const_iterator, value_type, const_reference, + difference_type> const_reverse_iterator; +# endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + + 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+ __STL_NULL_TMPL_ARGS (const rope<charT,Alloc> &left, + const rope<charT,Alloc> &right); + + friend rope<charT,Alloc> + operator+ __STL_NULL_TMPL_ARGS (const rope<charT,Alloc> &left, + const charT* right); + + friend rope<charT,Alloc> + operator+ __STL_NULL_TMPL_ARGS (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 + iterator erase(const iterator &p, const iterator &q) { + size_t p_index = p.index(); + erase(p_index, q.index() - p_index); + return iterator(this, p_index); + } + iterator erase(const iterator &p) { + size_t p_index = p.index(); + erase(p_index, 1); + return iterator(this, p_index); + } + + 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())); + } + +# ifdef __STL_CLASS_PARTIAL_SPECIALIZATION + typedef reverse_iterator<iterator> reverse_iterator; +# else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + typedef reverse_iterator<iterator, value_type, reference, + difference_type> reverse_iterator; +# endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + + 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); +} + +#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER + +template <class charT, class Alloc> +inline void swap(rope<charT, Alloc>& x, rope<charT, Alloc>& y) { + x.swap(y); +} + +#else + +inline void swap(crope x, crope y) { x.swap(y); } +inline void swap(wrope x, wrope y) { x.swap(y); } + +#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */ + +// Hash functions should probably be revisited later: +__STL_TEMPLATE_NULL 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; + } +}; + + +__STL_TEMPLATE_NULL 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; + } +}; + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma reset woff 1174 +#endif + +__STL_END_NAMESPACE + +# include <ropeimpl.h> +# endif /* __SGI_STL_INTERNAL_ROPE_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_set.h b/libstdc++/stl/stl_set.h new file mode 100644 index 00000000000..9ffeaa799a7 --- /dev/null +++ b/libstdc++/stl/stl_set.h @@ -0,0 +1,198 @@ +/* + * + * 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,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. + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_SET_H +#define __SGI_STL_INTERNAL_SET_H + +__STL_BEGIN_NAMESPACE + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma set woff 1174 +#endif + +#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 typename rep_type::const_pointer pointer; + typedef typename rep_type::const_pointer const_pointer; + typedef typename rep_type::const_reference reference; + typedef typename rep_type::const_reference const_reference; + typedef typename rep_type::const_iterator iterator; + typedef typename rep_type::const_iterator const_iterator; + typedef typename rep_type::const_reverse_iterator reverse_iterator; + typedef typename rep_type::const_reverse_iterator const_reverse_iterator; + typedef typename rep_type::size_type size_type; + typedef typename 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<typename 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) { + typedef typename rep_type::iterator rep_iterator; + return t.insert_unique((rep_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) { + typedef typename rep_type::iterator rep_iterator; + t.erase((rep_iterator&)position); + } + size_type erase(const key_type& x) { + return t.erase(x); + } + void erase(iterator first, iterator last) { + typedef typename rep_type::iterator rep_iterator; + t.erase((rep_iterator&)first, (rep_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== __STL_NULL_TMPL_ARGS (const set&, const set&); + friend bool operator< __STL_NULL_TMPL_ARGS (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; +} + +#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER + +template <class Key, class Compare, class Alloc> +inline void swap(set<Key, Compare, Alloc>& x, + set<Key, Compare, Alloc>& y) { + x.swap(y); +} + +#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */ + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma reset woff 1174 +#endif + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_INTERNAL_SET_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_slist.h b/libstdc++/stl/stl_slist.h new file mode 100644 index 00000000000..f31ea9e15e5 --- /dev/null +++ b/libstdc++/stl/stl_slist.h @@ -0,0 +1,740 @@ +/* + * 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. + * + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_SLIST_H +#define __SGI_STL_INTERNAL_SLIST_H + + +__STL_BEGIN_NAMESPACE + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma set woff 1174 +#endif + +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, class Ptr> +struct __slist_iterator : public __slist_iterator_base +{ + typedef __slist_iterator<T, T&, T*> iterator; + typedef __slist_iterator<T, const T&, const T*> const_iterator; + typedef __slist_iterator<T, Ref, Ptr> self; + + typedef T value_type; + typedef Ptr pointer; + typedef Ref 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) {} + + reference operator*() const { return ((list_node*) node)->data; } +#ifndef __SGI_STL_NO_ARROW_OPERATOR + pointer operator->() const { return &(operator*()); } +#endif /* __SGI_STL_NO_ARROW_OPERATOR */ + + self& operator++() + { + incr(); + return *this; + } + self operator++(int) + { + self tmp = *this; + incr(); + return tmp; + } +}; + +#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION + +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, class Ptr> +inline T* +value_type(const __slist_iterator<T, Ref, Ptr>&) { + return 0; +} + +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +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 const value_type* const_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, T&, T*> iterator; + typedef __slist_iterator<T, const T&, const T*> 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(); + __STL_TRY { + construct(&node->data, x); + node->next = 0; + } + __STL_UNWIND(list_node_allocator::deallocate(node)); + return node; + } + + 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; + __STL_TRY { + _insert_after_fill(&head, n, x); + } + __STL_UNWIND(clear()); + } + +#ifdef __STL_MEMBER_TEMPLATES + template <class InputIterator> + void range_initialize(InputIterator first, InputIterator last) { + head.next = 0; + __STL_TRY { + _insert_after_range(&head, first, last); + } + __STL_UNWIND(clear()); + } +#else /* __STL_MEMBER_TEMPLATES */ + void range_initialize(const value_type* first, const value_type* last) { + head.next = 0; + __STL_TRY { + _insert_after_range(&head, first, last); + } + __STL_UNWIND(clear()); + } + void range_initialize(const_iterator first, const_iterator last) { + head.next = 0; + __STL_TRY { + _insert_after_range(&head, first, last); + } + __STL_UNWIND(clear()); + } +#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== __STL_NULL_TMPL_ARGS(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 */ + + list_node_base* erase_after(list_node_base* pos) { + list_node* next = (list_node*) (pos->next); + list_node_base* next_next = next->next; + pos->next = next_next; + destroy_node(next); + return next_next; + } + + list_node_base* 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; + return 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: + iterator erase_after(iterator pos) { + return iterator((list_node*)erase_after(pos.node)); + } + iterator erase_after(iterator before_first, iterator last) { + return iterator((list_node*)erase_after(before_first.node, last.node)); + } + + iterator erase(iterator pos) { + return (list_node*) erase_after(__slist_previous(&head, pos.node)); + } + iterator erase(iterator first, iterator last) { + return (list_node*) 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()); +} + +#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER + +template <class T, class Alloc> +inline void swap(slist<T, Alloc>& x, slist<T, Alloc>& y) { + x.swap(y); +} + +#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */ + + +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 */ + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma reset woff 1174 +#endif + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_INTERNAL_SLIST_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_stack.h b/libstdc++/stl/stl_stack.h new file mode 100644 index 00000000000..d380e81dd1f --- /dev/null +++ b/libstdc++/stl/stl_stack.h @@ -0,0 +1,76 @@ +/* + * + * 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,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. + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_STACK_H +#define __SGI_STL_INTERNAL_STACK_H + +__STL_BEGIN_NAMESPACE + +#ifndef __STL_LIMITED_DEFAULT_TEMPLATES +template <class T, class Sequence = deque<T> > +#else +template <class T, class Sequence> +#endif +class stack { + friend bool operator== __STL_NULL_TMPL_ARGS (const stack&, const stack&); + friend bool operator< __STL_NULL_TMPL_ARGS (const stack&, const stack&); +public: + typedef typename Sequence::value_type value_type; + typedef typename Sequence::size_type size_type; + typedef typename Sequence::reference reference; + typedef typename Sequence::const_reference const_reference; +protected: + Sequence c; +public: + bool empty() const { return c.empty(); } + size_type size() const { return c.size(); } + reference top() { return c.back(); } + const_reference 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; +} + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_INTERNAL_STACK_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_tempbuf.h b/libstdc++/stl/stl_tempbuf.h new file mode 100644 index 00000000000..5c971e6208a --- /dev/null +++ b/libstdc++/stl/stl_tempbuf.h @@ -0,0 +1,123 @@ +/* + * + * 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,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. + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_TEMPBUF_H +#define __SGI_STL_INTERNAL_TEMPBUF_H + + +__STL_BEGIN_NAMESPACE + +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 +#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION + = iterator_traits<ForwardIterator>::value_type +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + > +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) { + __STL_TRY { + len = 0; + distance(first, last, len); + allocate_buffer(); + if (len > 0) + initialize_buffer(*first, + __type_traits<T>::has_trivial_default_constructor()); + } + __STL_UNWIND(free(buffer); buffer = 0; len = 0); + } + + ~temporary_buffer() { + destroy(buffer, buffer + len); + free(buffer); + } + +private: + temporary_buffer(const temporary_buffer&) {} + void operator=(const temporary_buffer&) {} +}; + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_INTERNAL_TEMPBUF_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_tree.h b/libstdc++/stl/stl_tree.h new file mode 100644 index 00000000000..55a6c0e53b2 --- /dev/null +++ b/libstdc++/stl/stl_tree.h @@ -0,0 +1,1099 @@ +/* + * + * 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. + * + * + * 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. + * + * + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_TREE_H +#define __SGI_STL_INTERNAL_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 <stl_algobase.h> +#include <stl_alloc.h> +#include <stl_construct.h> +#include <stl_function.h> + +__STL_BEGIN_NAMESPACE + +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, class Ptr> +struct __rb_tree_iterator : public __rb_tree_base_iterator +{ + typedef Value value_type; + typedef Ref reference; + typedef Ptr pointer; + typedef __rb_tree_iterator<Value, Value&, Value*> iterator; + typedef __rb_tree_iterator<Value, const Value&, const Value*> const_iterator; + typedef __rb_tree_iterator<Value, Ref, Ptr> 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; } + + reference operator*() const { return link_type(node)->value_field; } +#ifndef __SGI_STL_NO_ARROW_OPERATOR + pointer operator->() const { return &(operator*()); } +#endif /* __SGI_STL_NO_ARROW_OPERATOR */ + + 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; +} + +#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION + +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, class Ptr> +inline Value* value_type(const __rb_tree_iterator<Value, Ref, Ptr>&) { + return (Value*) 0; +} + +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + +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; + __STD::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(); + __STL_TRY { + construct(&tmp->value_field, x); + } + __STL_UNWIND(put_node(tmp)); + return tmp; + } + + 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, pointer> iterator; + typedef __rb_tree_iterator<value_type, const_reference, const_pointer> + const_iterator; + +#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION + typedef reverse_iterator<const_iterator> const_reverse_iterator; + typedef reverse_iterator<iterator> reverse_iterator; +#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + 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; +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ +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()) + : node_count(0), key_compare(comp) { init(); } + + rb_tree(const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& x) + : node_count(0), key_compare(x.key_compare) + { + header = get_node(); + color(header) = __rb_tree_red; + if (x.root() == 0) { + root() = 0; + leftmost() = header; + rightmost() = header; + } + else { + __STL_TRY { + root() = __copy(x.root(), header); + } + __STL_UNWIND(put_node(header)); + 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) { + __STD::swap(header, t.header); + __STD::swap(node_count, t.node_count); + __STD::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()); +} + +#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER + +template <class Key, class Value, class KeyOfValue, class Compare, class Alloc> +inline void swap(rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& x, + rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& y) { + x.swap(y); +} + +#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */ + + +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> +typename 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> +typename 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<typename 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> +typename 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> +typename 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> +typename 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> +typename 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; + + __STL_TRY { + 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); + } + } + __STL_UNWIND(__erase(top)); + + 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> +typename 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> +typename 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> +typename 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> +typename 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> +typename 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> +typename 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> +typename 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<typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator, + typename 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 KoV, class Compare, class Alloc> +inline pair<typename rb_tree<Key, Value, KoV, Compare, Alloc>::const_iterator, + typename rb_tree<Key, Value, KoV, Compare, Alloc>::const_iterator> +rb_tree<Key, Value, KoV, 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; +} + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_INTERNAL_TREE_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_uninitialized.h b/libstdc++/stl/stl_uninitialized.h new file mode 100644 index 00000000000..661bbe998e4 --- /dev/null +++ b/libstdc++/stl/stl_uninitialized.h @@ -0,0 +1,242 @@ +/* + * + * 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,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. + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_UNINITIALIZED_H +#define __SGI_STL_INTERNAL_UNINITIALIZED_H + +__STL_BEGIN_NAMESPACE + +// 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; + __STL_TRY { + for ( ; first != last; ++first, ++cur) + construct(&*cur, *first); + return cur; + } + __STL_UNWIND(destroy(result, cur)); +} + + +template <class InputIterator, class ForwardIterator, class T> +inline ForwardIterator +__uninitialized_copy(InputIterator first, InputIterator last, + ForwardIterator result, T*) { + typedef typename __type_traits<T>::is_POD_type is_POD; + return __uninitialized_copy_aux(first, last, result, is_POD()); +} + +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> +pair<InputIterator, ForwardIterator> +__uninitialized_copy_n(InputIterator first, Size count, + ForwardIterator result, + input_iterator_tag) { + ForwardIterator cur = result; + __STL_TRY { + for ( ; count > 0 ; --count, ++first, ++cur) + construct(&*cur, *first); + return pair<InputIterator, ForwardIterator>(first, cur); + } + __STL_UNWIND(destroy(result, cur)); +} + +template <class RandomAccessIterator, class Size, class ForwardIterator> +inline pair<RandomAccessIterator, ForwardIterator> +__uninitialized_copy_n(RandomAccessIterator first, Size count, + ForwardIterator result, + random_access_iterator_tag) { + RandomAccessIterator last = first + count; + return make_pair(last, uninitialized_copy(first, last, result)); +} + +template <class InputIterator, class Size, class ForwardIterator> +inline pair<InputIterator, 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; + __STL_TRY { + for ( ; cur != last; ++cur) + construct(&*cur, x); + } + __STL_UNWIND(destroy(first, cur)); +} + +template <class ForwardIterator, class T, class T1> +inline void __uninitialized_fill(ForwardIterator first, ForwardIterator last, + const T& x, T1*) { + typedef typename __type_traits<T1>::is_POD_type is_POD; + __uninitialized_fill_aux(first, last, x, is_POD()); + +} + +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; + __STL_TRY { + for ( ; n > 0; --n, ++cur) + construct(&*cur, x); + return cur; + } + __STL_UNWIND(destroy(first, cur)); +} + +template <class ForwardIterator, class Size, class T, class T1> +inline ForwardIterator __uninitialized_fill_n(ForwardIterator first, Size n, + const T& x, T1*) { + typedef typename __type_traits<T1>::is_POD_type is_POD; + return __uninitialized_fill_n_aux(first, n, x, is_POD()); + +} + +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); + __STL_TRY { + return uninitialized_copy(first2, last2, mid); + } + __STL_UNWIND(destroy(result, mid)); +} + +// 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); + __STL_TRY { + return uninitialized_copy(first, last, mid); + } + __STL_UNWIND(destroy(result, mid)); +} + +// 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); + __STL_TRY { + uninitialized_fill(mid2, last2, x); + } + __STL_UNWIND(destroy(first2, mid2)); +} + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_INTERNAL_UNINITIALIZED_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/stl_vector.h b/libstdc++/stl/stl_vector.h new file mode 100644 index 00000000000..cfa7fdb62d3 --- /dev/null +++ b/libstdc++/stl/stl_vector.h @@ -0,0 +1,534 @@ +/* + * + * 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. + */ + +/* NOTE: This is an internal header file, included by other STL headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_VECTOR_H +#define __SGI_STL_INTERNAL_VECTOR_H + +__STL_BEGIN_NAMESPACE + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma set woff 1174 +#endif + +template <class T, class Alloc = alloc> +class vector { +public: + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_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; + +#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION + typedef reverse_iterator<const_iterator> const_reverse_iterator; + typedef reverse_iterator<iterator> reverse_iterator; +#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ + 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; +#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ +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); + } + + void fill_initialize(size_type n, const T& value) { + start = allocate_and_fill(n, value); + finish = start + n; + end_of_storage = finish; + } +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) / sizeof(T); } + 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) { fill_initialize(n, value); } + vector(int n, const T& value) { fill_initialize(n, value); } + vector(long n, const T& value) { fill_initialize(n, value); } + explicit vector(size_type n) { fill_initialize(n, T()); } + + 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(); + 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) { + __STD::swap(start, x.start); + __STD::swap(finish, x.finish); + __STD::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 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 pop_back() { + --finish; + destroy(finish); + } + iterator erase(iterator position) { + if (position + 1 != end()) + copy(position + 1, finish, position); + --finish; + destroy(finish); + return position; + } + iterator erase(iterator first, iterator last) { + iterator i = copy(last, finish, first); + destroy(i, finish); + finish = finish - (last - first); + return 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); + __STL_TRY { + uninitialized_fill_n(result, n, x); + return result; + } + __STL_UNWIND(data_allocator::deallocate(result, n)); + } + +#ifdef __STL_MEMBER_TEMPLATES + template <class ForwardIterator> + iterator allocate_and_copy(size_type n, + ForwardIterator first, ForwardIterator last) { + iterator result = data_allocator::allocate(n); + __STL_TRY { + uninitialized_copy(first, last, result); + return result; + } + __STL_UNWIND(data_allocator::deallocate(result, n)); + } +#else /* __STL_MEMBER_TEMPLATES */ + iterator allocate_and_copy(size_type n, + const_iterator first, const_iterator last) { + iterator result = data_allocator::allocate(n); + __STL_TRY { + uninitialized_copy(first, last, result); + return result; + } + __STL_UNWIND(data_allocator::deallocate(result, n)); + } +#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 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); + +#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()); +} + +#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER + +template <class T, class Alloc> +inline void swap(vector<T, Alloc>& x, vector<T, Alloc>& y) { + x.swap(y); +} + +#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */ + +template <class T, class Alloc> +vector<T, Alloc>& vector<T, Alloc>::operator=(const vector<T, Alloc>& x) { + if (&x != this) { + if (x.size() > capacity()) { + 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; + iterator new_start = data_allocator::allocate(len); + iterator new_finish = new_start; + __STL_TRY { + 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; + 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); + iterator new_start = data_allocator::allocate(len); + iterator new_finish = new_start; + __STL_TRY { + 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; + 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); + iterator new_start = data_allocator::allocate(len); + iterator new_finish = new_start; + __STL_TRY { + 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 (size_type(end_of_storage - finish) >= n) { + const size_type elems_after = finish - position; + 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); + iterator new_start = data_allocator::allocate(len); + iterator new_finish = new_start; + __STL_TRY { + 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 */ + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +#pragma reset woff 1174 +#endif + +__STL_END_NAMESPACE + +#endif /* __SGI_STL_INTERNAL_VECTOR_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/tempbuf.h b/libstdc++/stl/tempbuf.h index 18d995252d8..8799393f39f 100644 --- a/libstdc++/stl/tempbuf.h +++ b/libstdc++/stl/tempbuf.h @@ -27,95 +27,32 @@ #ifndef __SGI_STL_TEMPBUF_H #define __SGI_STL_TEMPBUF_H +#ifndef __SGI_STL_PAIR_H +#include <pair.h> +#endif #include <limits.h> #include <stddef.h> #include <stdlib.h> -#include <pair.h> +#ifndef __TYPE_TRAITS_H #include <type_traits.h> +#endif +#ifndef __SGI_STL_INTERNAL_CONSTRUCT_H +#include <stl_construct.h> +#endif +#ifndef __SGI_STL_INTERNAL_TEMPBUF_H +#include <stl_tempbuf.h> +#endif -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; +#ifdef __STL_USE_NAMESPACES - void allocate_buffer() { - original_len = len; - buffer = 0; +using __STD::get_temporary_buffer; +using __STD::return_temporary_buffer; +using __STD::temporary_buffer; - 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 /* __STL_USE_NAMESPACES */ #endif /* __SGI_STL_TEMPBUF_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/tree.h b/libstdc++/stl/tree.h index 80e0cafa352..77c57cbbba1 100644 --- a/libstdc++/stl/tree.h +++ b/libstdc++/stl/tree.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 1996 + * Copyright (c) 1996,1997 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, modify, distribute and sell this software @@ -29,1069 +29,18 @@ #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> +#ifndef __SGI_STL_INTERNAL_TREE_H +#include <stl_tree.h> +#endif #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, class Ptr> -struct __rb_tree_iterator : public __rb_tree_base_iterator -{ - typedef Value value_type; - typedef Value& reference; - typedef Value* pointer; - typedef __rb_tree_iterator<Value, Value&, Value*> iterator; - typedef __rb_tree_iterator<Value, const Value&, const Value*> const_iterator; - typedef __rb_tree_iterator<Value, Ref, Ptr> 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; } - - reference operator*() const { return link_type(node)->value_field; } -#ifndef __SGI_STL_NO_ARROW_OPERATOR - pointer operator->() const { return &(operator*()); } -#endif /* __SGI_STL_NO_ARROW_OPERATOR */ - - 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; -} - -#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION - -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, class Ptr> -inline Value* value_type(const __rb_tree_iterator<Value, Ref, Ptr>&) { - return (Value*) 0; -} - -#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ - -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, pointer> iterator; - typedef __rb_tree_iterator<value_type, const_reference, const_pointer> - const_iterator; - -#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION - typedef reverse_iterator<const_iterator> const_reverse_iterator; - typedef reverse_iterator<iterator> reverse_iterator; -#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ - 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; -#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ -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()) - : node_count(0), key_compare(comp) { init(); } - - rb_tree(const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& x) - : node_count(0), key_compare(x.key_compare) { - 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; -} +#ifdef __STL_USE_NAMESPACES +using __STD::rb_tree; +#endif /* __STL_USE_NAMESPACES */ #endif /* __SGI_STL_TREE_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/type_traits.h b/libstdc++/stl/type_traits.h index 6ca0137709d..a7b977cc06b 100644 --- a/libstdc++/stl/type_traits.h +++ b/libstdc++/stl/type_traits.h @@ -15,7 +15,9 @@ #ifndef __TYPE_TRAITS_H #define __TYPE_TRAITS_H +#ifndef __STL_CONFIG_H #include <stl_config.h> +#endif /* This header file provides a framework for allowing compile time dispatch @@ -88,7 +90,7 @@ struct __type_traits { // have built-in __types_traits support, and essential for compilers // that don't. -struct __type_traits<char> { +__STL_TEMPLATE_NULL 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; @@ -96,7 +98,7 @@ struct __type_traits<char> { typedef __true_type is_POD_type; }; -struct __type_traits<signed char> { +__STL_TEMPLATE_NULL 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; @@ -104,7 +106,7 @@ struct __type_traits<signed char> { typedef __true_type is_POD_type; }; -struct __type_traits<unsigned char> { +__STL_TEMPLATE_NULL 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; @@ -112,7 +114,7 @@ struct __type_traits<unsigned char> { typedef __true_type is_POD_type; }; -struct __type_traits<short> { +__STL_TEMPLATE_NULL 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; @@ -120,7 +122,7 @@ struct __type_traits<short> { typedef __true_type is_POD_type; }; -struct __type_traits<unsigned short> { +__STL_TEMPLATE_NULL 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; @@ -128,7 +130,7 @@ struct __type_traits<unsigned short> { typedef __true_type is_POD_type; }; -struct __type_traits<int> { +__STL_TEMPLATE_NULL 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; @@ -136,7 +138,7 @@ struct __type_traits<int> { typedef __true_type is_POD_type; }; -struct __type_traits<unsigned int> { +__STL_TEMPLATE_NULL 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; @@ -144,7 +146,7 @@ struct __type_traits<unsigned int> { typedef __true_type is_POD_type; }; -struct __type_traits<long> { +__STL_TEMPLATE_NULL 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; @@ -152,7 +154,7 @@ struct __type_traits<long> { typedef __true_type is_POD_type; }; -struct __type_traits<unsigned long> { +__STL_TEMPLATE_NULL 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; @@ -160,7 +162,7 @@ struct __type_traits<unsigned long> { typedef __true_type is_POD_type; }; -struct __type_traits<float> { +__STL_TEMPLATE_NULL 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; @@ -168,7 +170,7 @@ struct __type_traits<float> { typedef __true_type is_POD_type; }; -struct __type_traits<double> { +__STL_TEMPLATE_NULL 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; @@ -176,7 +178,7 @@ struct __type_traits<double> { typedef __true_type is_POD_type; }; -struct __type_traits<long double> { +__STL_TEMPLATE_NULL 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; @@ -225,3 +227,7 @@ struct __type_traits<unsigned char*> { #endif /* __TYPE_TRAITS_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/utility b/libstdc++/stl/utility new file mode 100644 index 00000000000..df8c224388d --- /dev/null +++ b/libstdc++/stl/utility @@ -0,0 +1,38 @@ +/* + * + * 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,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_UTILITY +#define __SGI_STL_UTILITY + +#include <stl_config.h> +#include <stl_relops.h> +#include <stl_pair.h> + +#endif /* __SGI_STL_UTILITY */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/vector b/libstdc++/stl/vector new file mode 100644 index 00000000000..4bcdebcc186 --- /dev/null +++ b/libstdc++/stl/vector @@ -0,0 +1,41 @@ +/* + * + * 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 +#define __SGI_STL_VECTOR + +#include <stl_algobase.h> +#include <stl_alloc.h> +#include <stl_construct.h> +#include <stl_uninitialized.h> +#include <stl_vector.h> +#include <stl_bvector.h> + +#endif /* __SGI_STL_VECTOR */ + +// Local Variables: +// mode:C++ +// End: diff --git a/libstdc++/stl/vector.h b/libstdc++/stl/vector.h index 1c7867e8b03..231a227b7e3 100644 --- a/libstdc++/stl/vector.h +++ b/libstdc++/stl/vector.h @@ -27,507 +27,16 @@ #ifndef __SGI_STL_VECTOR_H #define __SGI_STL_VECTOR_H -#include <stddef.h> #include <algobase.h> #include <alloc.h> +#include <stl_vector.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; - -#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION - typedef reverse_iterator<const_iterator> const_reverse_iterator; - typedef reverse_iterator<iterator> reverse_iterator; -#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ - 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; -#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ -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); - } - - void fill_initialize(size_type n, const T& value) { - start = allocate_and_fill(n, value); - finish = start + n; - end_of_storage = finish; - } -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) / sizeof(T); } - 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) { fill_initialize(n, value); } - vector(int n, const T& value) { fill_initialize(n, value); } - vector(long n, const T& value) { fill_initialize(n, value); } - explicit vector(size_type n) { fill_initialize(n, T()); } - - 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(); - 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 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 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 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); - -#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()) { - 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; - 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; - 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); - 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; - 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); - 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 (size_type(end_of_storage - finish) >= n) { - const size_type elems_after = finish - position; - 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); - 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 */ +#ifdef __STL_USE_NAMESPACES +using __STD::vector; +#endif /* __STL_USE_NAMESPACES */ #endif /* __SGI_STL_VECTOR_H */ + +// Local Variables: +// mode:C++ +// End: |