/*
 * Copyright (c) 1999 Johnny C. Lam.
 * All rights reserved.
 *
 * 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.  The author makes no representations
 * about the suitability of this software for any purpose.  It is
 * provided "as is" without express or implied warranty.
 */

/* -*- C++ -*- */

#ifndef DP_AUTO_VECTOR_H
#define DP_AUTO_VECTOR_H

/*
 * This file implements auto_vector<T>, a strong vector (like a strong
 * pointer) which follows the coding pattern "Resource Management".
 */

using std::auto_ptr;

/*
 * Stupid non-compliant C++ compilers choke on the correct parent class.
 * It should be 
 * class __const_auto_iterator
 *     : public std::iterator<std::random_access_iterator_tag, const T*>
 */

template <typename T>
class __const_auto_iterator
    : public random_access_iterator<const T*, ptrdiff_t> {
private:
    typedef __const_auto_iterator self;

public:
    __const_auto_iterator();
    __const_auto_iterator(const auto_ptr<T>*);
    bool operator!=(const self&) const;

public:
    difference_type operator-(const self&) const;

    self operator++(int);
    self operator++();
    self operator+=(difference_type);
    self operator+(difference_type) const;

    self operator--(int);
    self operator--();
    self operator-=(difference_type);
    self operator-(difference_type) const;

public:
    const T* operator*();
    const T* operator->();

protected:
    const auto_ptr<T>* pp;
};

template <typename T>
class auto_vector {
public:
    typedef T element_type;
    typedef auto_ptr<T> value_type;
    typedef size_t size_type;
    typedef ptrdiff_t difference_type;

public:
    ~auto_vector();
    explicit auto_vector(size_type = 0);

    const T* operator[](size_type) const;
    T* operator[](size_type);

    void assign(size_type, auto_ptr<T>&);
    void assign_direct(size_type, T*);

    void push_back(auto_ptr<T>&);
    auto_ptr<T> pop_back();

public:
    typedef __const_auto_iterator<T> const_iterator;

public:
    const_iterator begin() const;
    const_iterator end() const;
    size_type size() const;

protected:
    void grow(size_type);

    auto_ptr<T>* array;
    size_type array_end;
    size_type capacity;
};

#include <dp_auto_vector_inline.h>
#include <dp_auto_vector.cc>

#endif /* DP_AUTO_VECTOR_H */
