#ifndef MXDYNBLOCK_INCLUDED // -*- C++ -*-
#define MXDYNBLOCK_INCLUDED
#if !defined(__GNUC__)
#  pragma once
#endif

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

  MxDynBlocks are blocks that automatically grow to fit the data added
  to them.

  Copyright (C) 1998 Michael Garland.  See "COPYING.txt" for details.
  
  $Id: MxDynBlock.h,v 1.14.2.1 2004/07/01 18:38:41 garland Exp $

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

#include "MxBlock.h"

template<class T>
class MxDynBlock : public MxBlock<T>
{
private:
    int fill;

public:
    MxDynBlock(int n=2) : MxBlock<T>(n) { fill=0; }

    int length() const { return fill; }
    int total_space() const { return MxBlock<T>::length(); }

    int      last_id() const { return fill-1; }
    T&       last()          { return (*this)[last_id()]; }
    const T& last() const    { return (*this)[last_id()]; }

    void room_for(int len)
    {
	if( length()<len ) resize(len);
	fill = len;
    }

    T& add()
    {
	if( length()==total_space() )  resize(total_space() * 2);
	fill++;
	return last();
    }

    void add(const T& t) { add() = t; }

    void reset() { fill = 0; }
    T& drop() { return (*this)[--fill]; }
    void drop(int d) { fill -= d; }

    void remove(int i) { (*this)[i] = (*this)[--fill]; }
    void remove_inorder(int i)
    	{ memmove(&(*this)[i], &(*this)[i+1], (--fill - i)*sizeof(T)); }

    // Restricted STL-like interface for interoperability with
    // STL-based code.  Overrides select MxBlock<> definitions and
    // introduces some additional std::vector-like methods.
    //
    int size() const { return length(); }

    typename MxBlock<T>::iterator end()       { return begin()+size(); }
    typename MxBlock<T>::const_iterator end() const { return begin()+size(); }

    void push_back(const T& t) { add(t); }
};

template<class T, int T_SIZE>
class MxSizedDynBlock : public MxDynBlock<T>
{
public:   MxSizedDynBlock(uint n=T_SIZE) : MxDynBlock<T>(n) { }
};

template<class T>
inline bool varray_find(const MxDynBlock<T>& A, const T& t, uint *index=NULL)
{
    for(unsigned int i=0; i<A.length(); i++)
	if( A[i] == t )
	{
	    if( index ) *index = i;
	    return true;
	}
    return false;
}

// MXDYNBLOCK_INCLUDED
#endif
