/***************************************************************************
 *
 * 23.vector.capacity.cpp - test exercising [lib.vector.capacity]
 *
 * $Id$
 *
 ***************************************************************************
 *
 * Copyright 2006 The Apache Software Foundation or its licensors,
 * as applicable.
 *
 * Copyright 2006 Rogue Wave Software.
 *
 * Licensed 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.
 * 
 **************************************************************************/

#include <memory>      // for placement operator new()
#include <vector>      // for vector

#include <cstddef>     // for size_t

#include <alg_test.h>
#include <driver.h>
#include <rw_new.h>

/**************************************************************************/

static int rw_opt_no_reserve_complexity;

/**************************************************************************/

// exercise vector<>::capacity() and vector<>::reserve()
// focus on the complexity of the function
void test_reserve_complexity () 
{
    rw_info (0, 0, 0, "std::vector<X>::capacity() const");
    rw_info (0, 0, 0, "std::vector<X>::reserve(size_type)");
    
    typedef std::vector<X, std::allocator<X> > Vector;
    
    bool success = true;
    Vector v;
    
    for (Vector::size_type i = 0; i < 16; ++i) {

        const X val;
        
        // push a value onto the end of the container
        v.push_back (val);
        
        const Vector::size_type cap  = v.capacity ();
        const Vector::size_type size = v.size ();

        X::reset_totals ();
        
        // call reserve with a larger capacity then is available
        v.reserve (cap + 1);
        
        // 23.2.4.2, p2: After reserve (), capacity () is greater or equal
        //               to the reserve value if reallocation happens
        rw_assert (v.capacity () >= cap + 1, 0, __LINE__,
                   "vector<X>::reserve(%zu); capacity() > %zu, got %zu",
                   cap + 1, cap, v.capacity ());

        // 23.2.3.2, p3: reserve shall not change the size of the sequence
        rw_assert (v.size () == size, 0, __LINE__,
                   "vector<X>::reserve(); size() == %zu, got %zu",
                   size, v.size ());
        
        // 23.2.3.2, p3: takes at most linear time in the size of the sequence 
        rw_assert (X::n_total_copy_ctor_ == v.size (), 0, __LINE__,
                   "vector<X>::reserve() - fails complexity "
                   "copy ctor called %zu size = %zu",
                   X::n_total_copy_ctor_, v.size ());
                                                        
#ifndef _RWSTD_NO_EXCEPTIONS

       // exercise reserve exception
        bool thrown = false;
        
        Vector::size_type too_much = v.max_size () + 1;
        if (!too_much)
            too_much = v.max_size ();

        try {
            v.reserve (too_much);
        }
        catch (...) {
            thrown = true;
        }

        rw_assert (thrown, 0, __LINE__, 
                   "vector<X>::reserve(%zu) - exception not thrown", too_much);
        
        
#endif // _RWSTD_NO_EXCEPTIONS
    }

    rw_assert (success, 0, __LINE__, "vector<X>::capacity()");
}

/**************************************************************************/

static int
run_test (int /* argc */, char** /* argv */)
{
    if (rw_opt_no_reserve_complexity) {
        rw_note (0, 0, __LINE__, "Reserve complexity test disabled.");
    }
    else {
        test_reserve_complexity ();
    }

    return 0;
}

/**************************************************************************/

int main (int argc, char** argv)
{
    return rw_test (argc, argv, __FILE__,
                    "lib.vector.capacity",
                    0 /* no comment */,
                    run_test, 
                    "|-no-reserve_complexity#",
                    &rw_opt_no_reserve_complexity);
}

