// ----------------------------------------------------------------------
//
// File: list_bug.cpp
//
// This module implements a List class for integers. (Buggy version.)
// The module is inteded for CTA++ demonstation purposes only.
// Copyright (c) 1998-2002 Testwell Oy
//
// Last edited: 12.12.2002
//
// ----------------------------------------------------------------------

#include "list.h"

// ----------------------------------------------------------------------
// NOTE: no implementation here for the functions 'List_malloc',
// 'List_realloc' and 'List_free' declared in header memory.h.
// They have stub implementations in the stub function include
// module CTA_memory.h_stb.inc
// ----------------------------------------------------------------------
#include "memory.h"

// **********************************************************************
//
// The methods of the class List
//
// **********************************************************************

// ----------------------------------------------------------------------
// List constructor
// ----------------------------------------------------------------------
List::List()
{
    last_element = 0;
    item_count = 0;
    list_size = LIST_STEP;

    the_list = static_cast<int*>(List_malloc(sizeof(int)*list_size));
    if (the_list == 0) {
        throw ExceptionOutOfMemory();
    }
}

// ----------------------------------------------------------------------
// List destructor
// ----------------------------------------------------------------------
List::~List()
{
    List_free(the_list);
}

// ----------------------------------------------------------------------
// List::insert
// ----------------------------------------------------------------------
void List::insert(int t)
{
    ++item_count;
    if (item_count > list_size) {
        int* reallocated_list;
        list_size *= 2;
        reallocated_list = static_cast<int*>(List_realloc(
            the_list,
            sizeof(int)*list_size));
        if (reallocated_list == 0) {
            throw ExceptionOutOfMemory();
        } else {
            the_list = reallocated_list;
        }
        last_element = the_list + item_count - 2;
    }
    
    if (last_element == 0) {
        last_element = the_list;
        *last_element = t;
    } else {
        ++last_element;
        *last_element = t;
    }
}

// ----------------------------------------------------------------------
// List::extract
// ----------------------------------------------------------------------
int List::extract()
{
    if (last_element != 0) {
/*correct*/ //   --item_count;
/*buggy*/      ;
        int item = *last_element;
        if (last_element != the_list) {
            --last_element;
        } else {
            last_element = 0;
        }
        return item;
    } else {
        throw ExceptionEmptyList();
        return 0;
    }
}

// ----------------------------------------------------------------------
// List::remove
// ----------------------------------------------------------------------
void List::remove(int t)
{
    bool found = false;
    if (last_element != 0) {
        int* tmp = the_list;
        for (; tmp <= last_element; ++tmp) {
            if (*tmp == t) {
/*buggy*/           for (int* tmp2 = tmp + 1; tmp2 < last_element; ++tmp2) {
/*correct*/  //      for (int* tmp2 = tmp + 1; tmp2 <= last_element; ++tmp2) {
                    *(tmp2 - 1) = *tmp2;
                }
                if (last_element == the_list) {
                    last_element = 0;
                } else {
                    --last_element;
                }
                found = true;
                --item_count;
                break;
            }
        }
    }
    if (!found) {
        // run-time error!
    }
}

// ----------------------------------------------------------------------
// List::begin
// ----------------------------------------------------------------------
List_iterator List::begin() const
{
    int* iter = 0;
 /*correct*/ //       if (last_element != 0) {
 /*buggy*/        if (last_element == 0) {
        iter = the_list;
    }
        
    return List_iterator(this, iter);
}

// ----------------------------------------------------------------------
// List::last
// ----------------------------------------------------------------------
List_iterator List::last() const
{
    return List_iterator(this, last_element);
}

// ----------------------------------------------------------------------
// List::rbegin
// ----------------------------------------------------------------------
List_reverse_iterator List::rbegin() const
{
    return List_reverse_iterator(this, last_element);
}

// ----------------------------------------------------------------------
// List::empty
// ----------------------------------------------------------------------
bool List::empty() const
{
    return static_cast<bool>(last_element == 0);
}

// ----------------------------------------------------------------------
// List::itemCount
// ----------------------------------------------------------------------
int List::itemCount() const
{
    return item_count;
}


// **********************************************************************
//
// The methods of the class List_iterator
//
// **********************************************************************

// ----------------------------------------------------------------------
// List_iterator constructor 1
// ----------------------------------------------------------------------
List_iterator::List_iterator(const List* l)
{
    iter_list = 0;
    list = l;
}

// ----------------------------------------------------------------------
// List_iterator constructor 2
// ----------------------------------------------------------------------
List_iterator::List_iterator(const List* l, int* iter)
{
    iter_list = iter;
    list = l;
}

// ----------------------------------------------------------------------
// List_iterator::end
// ----------------------------------------------------------------------
bool List_iterator::end() const
{
    return static_cast<bool>(iter_list == 0);
}

// ----------------------------------------------------------------------
// List_iterator::operator*
// ----------------------------------------------------------------------
int List_iterator::operator*()
{
    if (iter_list != 0) {
        return *iter_list;
    } else {
        // run-time error!
        throw ExceptionIteratorOutOfBounds("operator *");
        return 0;
    }
}

// ----------------------------------------------------------------------
// List_iterator::operator++
// ----------------------------------------------------------------------
List_iterator& List_iterator::operator++()
{
    if (iter_list == list->last_element && iter_list != 0) {
        iter_list = 0;
    } else if (iter_list != 0) {
        ++iter_list;
    } else {
        // run-time error!
        throw ExceptionIteratorOutOfBounds("operator ++");
    }
    return *this;
}


// **********************************************************************
//
// Methods of the class List_reverse_iterator
//
// **********************************************************************

// ----------------------------------------------------------------------
// List_reverse_iterator constructor 1
// ----------------------------------------------------------------------
List_reverse_iterator::List_reverse_iterator(const List* l)
{
    list = l;
    iter_list = 0;
}

// ----------------------------------------------------------------------
// List_reverse_iterator constructor 2
// ----------------------------------------------------------------------
List_reverse_iterator::List_reverse_iterator(const List* l, int* iter)
{
    list = l;
    iter_list = iter;
}

// ----------------------------------------------------------------------
// List_reverse_iterator::rend
// ----------------------------------------------------------------------
bool List_reverse_iterator::rend()
{
    return static_cast<bool>(iter_list == 0 || iter_list == list->the_list);
}

// ----------------------------------------------------------------------
// List_reverse_iterator::operator*
// ----------------------------------------------------------------------
int List_reverse_iterator::operator*()
{
    return *iter_list;
}

// ----------------------------------------------------------------------
// List_reverse_iterator::operator--
// ----------------------------------------------------------------------
List_reverse_iterator& List_reverse_iterator::operator--()
{
    if (iter_list != 0 && iter_list !=list->the_list) {
        --iter_list;
    } else {
        // run-time error!
        throw ExceptionIteratorOutOfBounds("operator --");
    }
    return *this;
}

// EOF