/*****************************************************************************
 * $LastChangedDate: 2011-04-23 21:07:07 -0400 (Sat, 23 Apr 2011) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   Array template class based on Shared.
 * @verbatim
 *
 * These arrays are very specialized and have both advantaes and disadvantages.
 *
 * PTR() guidelines:
 * -----------------
 * PTR() has limited uses.
 * Acceptable uses are inside frequent functions that use PTR() in their own scope.
 * PTR() opens the pitfall of dangling pointers.
 * Never store (or pass to a function that may store) what PTR() returns.
 * Be sure that what PTR() returned isn't still used after its object was destroyed.
 *
 * Coding notes:
 * -------------
 * if ( a > b )        // problem is that operator>() is rarely defined
 * if ( not (a < b) )  // WRONG: that's >=
 * if ( b < a )        // right: swapping operands of < is equivalent to >
 *
 * @endverbatim
 *//*
 * LEGAL:   COPYRIGHT (C) 2007 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
 *****************************************************************************/

#ifndef BASE_ARRAY_HH
#define BASE_ARRAY_HH 1

#include <vector>
#include "base/types.hh"

namespace base {

////////////////////////////////////////////////////////////////////////////////
/// @brief Array template class similar to STL vector but checks index and can be Shared.
///
/// @verbatim
///
/// Thin wrapper over STL vector which does bounds checking.
/// PTR() returns raw C array.
/// If size of array is pre-determined, for speed,
/// construct and write elements using Array(uint) and operator[] resp.
/// Rules for writing elements:
/// - Must use push_back() if constructed by Array(void).
/// - Writing elements by operator[] allowed if constructed by Array(uint).
///
/// Array currently doesn't but could allocate an extra element to tolerate off-by-one errors.
///
/// @endverbatim
///
template<typename T>
class Array : public Shared
{
COPYABLE(Array)
public:
    typedef T Type;
    // Writing new elements is restricted to push_back().
    Array( void ) { }
    // Writing new elements can be done by operator[].
    explicit Array( uint count ) { ASSERT( count < MAX_ELEMS ); mVector.resize( count ); }
    ~Array() { }
    /// @returns Raw C array.
    /// PTR() IS UNDEFINED IF ARRAY IS EMPTY!
    /// Subtlety: &vector[0] is in fact a C array.  But &vector is address of STL vector object.
    T*                PTR( void ) const { return const_cast<T*>( &mVector[0] ); }
    const T*    CONST_PTR( void ) const { return &mVector[0]; }
    T&          operator[]( uint i )       { ASSERT( i < mVector.size() ); return mVector[i]; }
    const T&    operator[]( uint i ) const { ASSERT( i < mVector.size() ); return mVector[i]; }
    void        push_back( const T& v ) { mVector.push_back( v ); }
    bool        empty( void ) const { return mVector.empty(); }
    void        clear( void ) { mVector.clear(); }
    uint        size( void ) const  { return mVector.size(); }
    void        resize( uint count )  { mVector.resize( count ); }  // immediate reallocation
    void        reserve( uint count ) { mVector.reserve( count ); }  // just a hint for allocator
    friend bool operator<( const Array& a, const Array& b ) { return a.mVector < b.mVector; }

//  typedef STLIterator<T,vector<T> > Iterator;
//  Iterator    GetIterator( void ) const { return Iterator( mVector ); }

private:
    std::vector<T>      mVector;
    CLASS_CONST uint    MAX_ELEMS = 20 * MILLION;
};

} // namespace base

#endif // BASE_ARRAY_HH
