// -*- C++ -*-
/***************************************************************************
 *
 * _specialized.h - definitions of specialized algorithms
 *
 * This is an internal header file used to implement the C++ Standard
 * Library. It should never be #included directly by a program.
 *
 * $Id: _specialized.h 605548 2007-12-19 14:19:33Z faridz $
 *
 ***************************************************************************
 *
 * Licensed to the Apache Software  Foundation (ASF) under one or more
 * contributor  license agreements.  See  the NOTICE  file distributed
 * with  this  work  for  additional information  regarding  copyright
 * ownership.   The ASF  licenses this  file to  you under  the Apache
 * License, Version  2.0 (the  "License"); you may  not use  this file
 * except in  compliance with the License.   You may obtain  a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the  License is distributed on an  "AS IS" BASIS,
 * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY  KIND, either  express or
 * implied.   See  the License  for  the  specific language  governing
 * permissions and limitations under the License.
 *
 * Copyright 1994-2006 Rogue Wave Software.
 *
 ***************************************************************************
 *
 * 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 _RWSTD_RW_SPECIALIZED_H_INCLUDED
#define _RWSTD_RW_SPECIALIZED_H_INCLUDED


#ifndef _RWSTD_RW_NEW_H_INCLUDED
#  include <rw/_new.h>
#endif   // _RWSTD_RW_NEW_H_INCLUDED


_RWSTD_NAMESPACE (__rw) { 


#ifndef _RWSTD_NO_NONDEDUCED_CONTEXT
#  define _RWSTD_CONTAINER_SIZE_TYPE _TYPENAME _Container::size_type
#else
#  define _RWSTD_CONTAINER_SIZE_TYPE _RWSTD_SIZE_T
#endif   // _RWSTD_NO_NONDEDUCED_CONTEXT


// returns a suggested new capacity for a container needing more space
template <class _Container>
inline _RWSTD_CONTAINER_SIZE_TYPE
__rw_new_capacity (_RWSTD_CONTAINER_SIZE_TYPE __size, const _Container*)
{
    typedef _RWSTD_CONTAINER_SIZE_TYPE _RWSizeT;

    const _RWSizeT __ratio = _RWSizeT (  (_RWSTD_NEW_CAPACITY_RATIO << 10)
                                       / _RWSTD_RATIO_DIVIDER);

    const _RWSizeT __cap =   (__size >> 10) * __ratio
                           + (((__size & 0x3ff) * __ratio) >> 10);

    return (__size += _RWSTD_MINIMUM_NEW_CAPACITY) > __cap ? __size : __cap;
}                     

#undef _RWSTD_CONTAINER_SIZE_TYPE


#ifndef _RWSTD_NO_PART_SPEC_OVERLOAD

template <class _TypeT, class _TypeU>
inline void
__rw_construct (_TypeT* __p, _TypeU& __val)
{
    ::new (_RWSTD_STATIC_CAST (void*, __p)) _TypeT (__val);
}


template <class _TypeT, class _TypeU>
inline void
__rw_construct (volatile _TypeT* __p, _TypeU& __val)
{
    // remove volatile before invoking operator new
    __rw_construct (_RWSTD_CONST_CAST (_TypeT*, __p), __val);
}

#else   // #ifdef _RWSTD_NO_PART_SPEC_OVERLOAD

template <class _TypeT, class _TypeU>
inline void
__rw_construct_impl (_TypeT* __p, _TypeU& __val)
{
    ::new (_RWSTD_STATIC_CAST (void*, __p)) _TypeT (__val);
}


template <class _TypeT, class _TypeU>
inline void
__rw_construct (volatile _TypeT* __p, _TypeU& __val)
{
    // remove volatile before invoking operator new
    __rw_construct_impl (_RWSTD_CONST_CAST (_TypeT*, __p), __val);
}

#endif  // _RWSTD_NO_PART_SPEC_OVERLOAD

template <class _TypeT>
inline void
__rw_destroy (_TypeT &__ref)
{
    __ref.~_TypeT ();
}


template <class _ForwardIterator> 
inline void
__rw_destroy (_ForwardIterator __first, _ForwardIterator __last)
{
    for (; __first != __last; ++__first)
        __rw_destroy (*__first);
}


#ifndef _RWSTD_NO_PTR_VALUE_TEMPLATE_OVERLOAD

// for compilers that don't optimize "empty" loops
template <class _TypeT> 
inline void __rw_destroy (_TypeT**, _TypeT**)
{ }

#endif   // _RWSTD_NO_PTR_VALUE_TEMPLATE_OVERLOAD


}   // namespace __rw


_RWSTD_NAMESPACE (std) { 

template <class _TypeT>
class allocator;


// 20.4.4.1
template <class _InputIterator, class _ForwardIterator>
inline _ForwardIterator
uninitialized_copy (_InputIterator __first, _InputIterator __last,
                    _ForwardIterator __res)
{
    const _ForwardIterator __start = __res;

    _TRY {
        for (; __first != __last; ++__first, ++__res)
            _RW::__rw_construct (&*__res, *__first);
    }
    _CATCH (...) {
        _RW::__rw_destroy (__start, __res);
        _RETHROW;
    }

    return __res;
}


#ifdef _RWSTD_ALLOCATOR

// extension
template <class _InputIterator, class _ForwardIterator, class _Allocator>
inline _ForwardIterator
uninitialized_copy (_InputIterator __first, _InputIterator __last,
                    _ForwardIterator __res, _Allocator &__alloc)
{
    _ForwardIterator __start = __res;

    _TRY {
        for (; __first != __last; ++__first, ++__res)
            __alloc.construct (__alloc.address (*__res), *__first);
    }
    _CATCH (...) {
        for (; __start != __res; ++__start)
            __alloc.destroy (__alloc.address (*__start));
        _RETHROW;
    }

    return __res;
}

#endif   // _RWSTD_ALLOCATOR


// 20.4.4.2
template <class _ForwardIterator, class _TypeT>
inline void
uninitialized_fill (_ForwardIterator __first, _ForwardIterator __last,
                    const _TypeT& __x)
{
    const _ForwardIterator __start = __first;

    _TRY {
        for (; __first != __last; ++__first)
            _RW::__rw_construct (&*__first, __x);
    }
    _CATCH (...) {
        _RW::__rw_destroy (__start, __first);
        _RETHROW;
    }
}


// 20.4.4.3
template <class _ForwardIterator, class _Size, class _TypeT>
inline void
uninitialized_fill_n (_ForwardIterator __first, _Size __n, const _TypeT& __x)
{
    const _ForwardIterator __start = __first;

    _TRY {
        for (; __n; --__n, ++__first)
            _RW::__rw_construct (&*__first, __x);
    }
    _CATCH (...) {
        _RW::__rw_destroy (__start, __first);
        _RETHROW;
    }
}


#ifdef _RWSTD_ALLOCATOR

// extension
template <class _ForwardIter, class _Size, class _TypeT, class _Allocator>
inline void
uninitialized_fill_n (_ForwardIter __first, _Size __n,
                      const _TypeT& __x, _Allocator& __alloc)
{
    _ForwardIter __start = __first;

    _TRY {
        for (; __n; --__n, ++__first)
            __alloc.construct (__alloc.address (*__first), __x);
    }
    _CATCH (...) {
        for (; __start != __first; ++__start)
            __alloc.destroy (__alloc.address (*__start));
        _RETHROW;
    }
}

#else   // if !defined (_RWSTD_ALLOCATOR)


template <class _Allocator, class _TypeT>
class allocator_interface;

// Specializations for non-standard allocators.  When vector calls
// uninitialized_{copy,fill_n} with non-standard allocator, a temporary
// instance of allocator_interface is passed to these functions.  Since
// C++ forbids temporaries to be passed as non-const references, we
// use these specializations to pass a const reference (and we can force
// allocator_interface members construct & destroy to be const).

template <class _InputIterator, class _ForwardIterator,
          class _Allocator, class _TypeT>
inline _ForwardIterator
uninitialized_copy (_InputIterator   __first,
                    _InputIterator   __last,
                    _ForwardIterator __res,
                    allocator_interface<_Allocator, _TypeT> &__alloc)
{
    _ForwardIterator __start = __res;

    _TRY {
        for (; __first != __last; ++__first, ++__res)
            __alloc.construct (__alloc.address (*__res), *__first);
    }
    _CATCH (...) {
        for (; __start != __res; ++__start)
            __alloc.destroy (__alloc.address (*__start));
        _RETHROW;
    }

    return __res;
}

template <class _ForwardIter, class _Size,
          class _TypeT, class _Allocator, class _TypeU>
inline void
uninitialized_fill_n (_ForwardIter __first, _Size __n,
                      const _TypeT& __x,
                      allocator_interface<_Allocator, _TypeU> &__alloc)
{
    _ForwardIter __start = __first;

    _TRY {
        for (; __n; --__n, ++__first)
            __alloc.construct (__alloc.address (*__first), __x);
    }
    _CATCH (...) {
        for (; __start != __first; ++__start)
            __alloc.destroy (__alloc.address (*__start));
        _RETHROW;
    }
}

#endif   // _RWSTD_ALLOCATOR

}   // namespace std


#endif   // _RWSTD_RW_SPECIALIZED_H_INCLUDED
