// "Dynamic memory" allocation.
// Also known as "free store", similar to
// "heap memory" allocation in C.

// This demo program demonstrates an object that
// manages dynamic memory. It is capable to grab some
// memory from the operating system, then ask for more
// memory and return back previously allocated block.
// One delinquency of this implementation is that at
// the end of its lifetime, the object never returns
// currently allocated dynamic memory back to the system.
// This will be fixed when we introduce destructors.

#include <cassert>
class DynStack {
public:
    const static int INITIAL_STACK_SIZE = 3;
private:
    int* m_ptr_stack_array;
    int m_stack_size;
public:
    DynStack() // constructor
    {
        //m_ptr_stack_array = new int[ INITIAL_STACK_SIZE ];
        m_stack_size = INITIAL_STACK_SIZE;
        m_ptr_stack_array = allocate_ints( m_stack_size );
        //deallocate_ints( m_ptr_stack_array );
        //m_ptr_stack_array = NULL;
    }
    int size()
    {
        return m_stack_size;
    }

    void double_capacity()
    {
        int* new_memory = allocate_ints( m_stack_size * 2 );
        //copy original data to the new area
        int idx = 0;
        for ( ; idx < m_stack_size; ++idx ) {
            new_memory[ idx ] = m_ptr_stack_array[ idx ];
        }
        deallocate_ints( m_ptr_stack_array ); // deallocate old memory
        m_ptr_stack_array = new_memory;
        m_stack_size = m_stack_size * 2;
        //m_stack_size *= 2;
    }
private:
    int* allocate_ints( int how_many )
    {
        int* new_memory = new int[ how_many ];
        return new_memory;
    }
    void deallocate_ints( int* ptr_mem )
    {
        delete[] ptr_mem;
    }
};

int main()
{
    DynStack st1;
    st1.double_capacity();
    const int DBL_INITIAL_SIZE = DynStack::INITIAL_STACK_SIZE * 2;
    assert( st1.size() == DBL_INITIAL_SIZE );
    return 0;
}