//  The C++ Booch Components (Version 2.0)
//  (C) Copyright 1990-1993 Grady Booch. All Rights Reserved.
//
//  BCDynami.h
//
//  This file contains the declaration of the dynamic array-based class
//  used for the representation of dynamic structures.

#ifndef BCDYNAMI_H
#define BCDYNAMI_H 1

#include <stddef.h>
#include "BCExcept.h"

// Class denoting an optimally-packed dynamic container

template<class Container_Item, class Storage_Manager>
class BC_TDynamic {
public:

  BC_TDynamic();
  BC_TDynamic(BC_Index chunkSize);
  BC_TDynamic(const BC_TDynamic<Container_Item, Storage_Manager>&);
  ~BC_TDynamic();

  BC_TDynamic<Container_Item, Storage_Manager>& operator=(const BC_TDynamic<Container_Item, Storage_Manager>&);
  BC_Boolean operator==(const BC_TDynamic<Container_Item, Storage_Manager>&) const;
  BC_Boolean operator!=(const BC_TDynamic<Container_Item, Storage_Manager>& c) const
    {return !operator==(c);}
  Container_Item& operator[](BC_Index index) const
    {BC_Assert((index < Length()),
               BC_XRangeError("BC_TDynamic<>::operator[]", BC_kInvalidIndex));
     return Item(index);}

  void SetChunkSize(BC_Index chunkSize)
    {BC_Assert((!fRepChunkSize),
               BC_XNotNull("BC_TDynamic<>::SetChunkSize", BC_kNotEmpty));
     fRepChunkSize = chunkSize;}
  void Preallocate(BC_Index new_length);
  void Clear();
  void Insert(const Container_Item&);
  void Insert(const Container_Item&, BC_Index before);
  void Append(const Container_Item&);
  void Append(const Container_Item&, BC_Index after);
  void Remove(BC_Index at);
  void Replace(BC_Index at, const Container_Item&);

  BC_Index ChunkSize() const
    {return fRepChunkSize;}
  BC_Index Length() const;
  const Container_Item& First() const
    {BC_Assert((fRepStart >= 0), BC_XUnderflow("BC_TDynamic<>::First()", BC_kEmpty));
     return fRep[fRepStart - 1];}
  const Container_Item& Last() const
    {return fRep[fRepStop - 1];}
  Container_Item& Item(BC_Index) const;
  BC_Extended_Index Location(const Container_Item&) const;

  static void* operator new(size_t);
  static void operator delete(void*, size_t);

protected:

  Container_Item* fRep;
  BC_Index fRepSize;
  BC_Index fRepTotalChunks;
  BC_Index fRepChunkSize;
  BC_Index fRepStart;
  BC_Index fRepStop;
  
  void Resize(BC_Index current_length, BC_Index new_length, BC_Boolean preserve = 1);

  BC_Index ExpandLeft(BC_Index from);
  BC_Index ExpandRight(BC_Index from);
  void ShrinkLeft(BC_Index from);
  void ShrinkRight(BC_Index from);
  
};

#endif
