This source file includes following definitions.
- Clear
 
- Allocate
 
- Reserve
 
- Add
 
- Erase
 
- Erase
 
- Insert
 
- Resize
 
- Resize
 
- Contains
 
#ifndef _NPT_ARRAY_H_
#define _NPT_ARRAY_H_
#include "NptConfig.h"
#if defined(NPT_CONFIG_HAVE_NEW_H)
#include <new>
#endif
#include "NptTypes.h"
#include "NptResults.h"
const int NPT_ARRAY_INITIAL_MAX_SIZE = 128; 
template <typename T> 
class NPT_Array 
{
public:
    
    typedef T Element;
    typedef T* Iterator;
    
    NPT_Array<T>(): m_Capacity(0), m_ItemCount(0), m_Items(0) {}
    explicit NPT_Array<T>(NPT_Cardinal count);
    NPT_Array<T>(NPT_Cardinal count, const T& item);
    NPT_Array<T>(const T* items, NPT_Cardinal item_count);
   ~NPT_Array<T>();
    NPT_Array<T>(const NPT_Array<T>& copy);
    NPT_Array<T>& operator=(const NPT_Array<T>& copy);
    bool          operator==(const NPT_Array<T>& other) const;
    bool          operator!=(const NPT_Array<T>& other) const;
    NPT_Cardinal GetItemCount() const { return m_ItemCount; }
    NPT_Result   Add(const T& item);
    T& operator[](NPT_Ordinal pos)             { return m_Items[pos]; }
    const T& operator[](NPT_Ordinal pos) const { return m_Items[pos]; }
    NPT_Result   Erase(Iterator which);
    NPT_Result   Erase(NPT_Ordinal which) { return Erase(&m_Items[which]); }
    NPT_Result   Erase(Iterator first, Iterator last);
    NPT_Result   Erase(NPT_Ordinal first, NPT_Ordinal last) { return Erase(&m_Items[first], &m_Items[last]); }
    NPT_Result   Insert(Iterator where, const T& item, NPT_Cardinal count = 1);
    NPT_Result   Reserve(NPT_Cardinal count);
    NPT_Cardinal GetCapacity() const { return m_Capacity; }
    NPT_Result   Resize(NPT_Cardinal count);
    NPT_Result   Resize(NPT_Cardinal count, const T& fill);
    NPT_Result   Clear();
    bool         Contains(const T& data) const;
    Iterator     GetFirstItem() const { return m_ItemCount?&m_Items[0]:NULL; }
    Iterator     GetLastItem() const  { return m_ItemCount?&m_Items[m_ItemCount-1]:NULL; }
    Iterator     GetItem(NPT_Ordinal n) { return n<m_ItemCount?&m_Items[n]:NULL; }
    
    
    
    template <typename X> 
    NPT_Result Apply(const X& function) const
    {                                  
        for (unsigned int i=0; i<m_ItemCount; i++) function(m_Items[i]);
        return NPT_SUCCESS;
    }
    template <typename X, typename P>
    NPT_Result ApplyUntil(const X& function, const P& predicate, bool* match = NULL) const
    {                                  
        for (unsigned int i=0; i<m_ItemCount; i++) {
            NPT_Result return_value;
            if (predicate(function(m_Items[i]), return_value)) {
                if (match) *match = true;
                return return_value;
            }
        }
        if (match) *match = false;
        return NPT_SUCCESS;
    }
    template <typename X> 
    T* Find(const X& predicate, NPT_Ordinal n=0, NPT_Ordinal* pos = NULL) const
    {
        if (pos) *pos = -1;
        for (unsigned int i=0; i<m_ItemCount; i++) {
            if (predicate(m_Items[i])) {
                if (pos) *pos = i;
                if (n == 0) return &m_Items[i];
                --n;
            }
        }
        return NULL;
    }
protected:
    
    T* Allocate(NPT_Cardinal count, NPT_Cardinal& allocated);
    
    NPT_Cardinal m_Capacity;
    NPT_Cardinal m_ItemCount;
    T*           m_Items;
};
template <typename T>
inline
NPT_Array<T>::NPT_Array(NPT_Cardinal count) :
    m_Capacity(0),
    m_ItemCount(0),
    m_Items(0)
{
    Reserve(count);
}
template <typename T>
inline
NPT_Array<T>::NPT_Array(const NPT_Array<T>& copy) :
    m_Capacity(0),
    m_ItemCount(0),
    m_Items(0)
{
    Reserve(copy.GetItemCount());
    for (NPT_Ordinal i=0; i<copy.m_ItemCount; i++) {
        new ((void*)&m_Items[i]) T(copy.m_Items[i]);
    }
    m_ItemCount = copy.m_ItemCount;
}
template <typename T>
inline
NPT_Array<T>::NPT_Array(NPT_Cardinal count, const T& item) :
    m_Capacity(0),
    m_ItemCount(count),
    m_Items(0)    
{
    Reserve(count);
    for (NPT_Ordinal i=0; i<count; i++) {
        new ((void*)&m_Items[i]) T(item);
    }
}
template <typename T>
inline
NPT_Array<T>::NPT_Array(const T* items, NPT_Cardinal item_count) :
    m_Capacity(0),
    m_ItemCount(item_count),
    m_Items(0)    
{
    Reserve(item_count);
    for (NPT_Ordinal i=0; i<item_count; i++) {
        new ((void*)&m_Items[i]) T(items[i]);
    }
}
template <typename T>
inline
NPT_Array<T>::~NPT_Array()
{
    
    Clear();
    
    ::operator delete((void*)m_Items);
}
template <typename T>
NPT_Array<T>&
NPT_Array<T>::operator=(const NPT_Array<T>& copy)
{
    
    if (this == ©) return *this;
    
    Clear();
    
    Reserve(copy.GetItemCount());
    m_ItemCount = copy.m_ItemCount;
    for (NPT_Ordinal i=0; i<copy.m_ItemCount; i++) {
        new ((void*)&m_Items[i]) T(copy.m_Items[i]);
    }
    return *this;
}
template <typename T>
NPT_Result
NPT_Array<T>::Clear()
{
    
    for (NPT_Ordinal i=0; i<m_ItemCount; i++) {
        m_Items[i].~T();
    }
    m_ItemCount = 0;
    return NPT_SUCCESS;
}
template <typename T>
T*
NPT_Array<T>::Allocate(NPT_Cardinal count, NPT_Cardinal& allocated) 
{
    if (m_Capacity) {
        allocated = 2*m_Capacity;
    } else {
        
        
        allocated = NPT_ARRAY_INITIAL_MAX_SIZE/sizeof(T);
        if (allocated == 0) allocated = 1;
    }
    if (allocated < count) allocated = count;
    
    return (T*)::operator new(allocated*sizeof(T));
}
template <typename T>
NPT_Result
NPT_Array<T>::Reserve(NPT_Cardinal count)
{
    if (count <= m_Capacity) return NPT_SUCCESS;
    
    NPT_Cardinal new_capacity;
    T* new_items = Allocate(count, new_capacity);
    if (new_items == NULL) {
        return NPT_ERROR_OUT_OF_MEMORY;
    }
    if (m_ItemCount && m_Items) {
        for (unsigned int i=0; i<m_ItemCount; i++) {
            
            new ((void*)&new_items[i])T(m_Items[i]);
            
            m_Items[i].~T();
        }
    }
    ::operator delete((void*)m_Items);
    m_Items = new_items;
    m_Capacity = new_capacity;
    return NPT_SUCCESS;
}
template <typename T>
inline
NPT_Result
NPT_Array<T>::Add(const T& item)
{
    
    NPT_Result result = Reserve(m_ItemCount+1);
    if (result != NPT_SUCCESS) return result;
    
    new ((void*)&m_Items[m_ItemCount++]) T(item);
    return NPT_SUCCESS;
}
template <typename T>
inline
NPT_Result
NPT_Array<T>::Erase(Iterator which)
{
    return Erase(which, which);
}
template <typename T>
NPT_Result
NPT_Array<T>::Erase(Iterator first, Iterator last)
{
    
    if (first == NULL || last == NULL) return NPT_ERROR_INVALID_PARAMETERS;
    
    NPT_Ordinal first_index = (NPT_Ordinal)(NPT_POINTER_TO_LONG(first-m_Items));
    NPT_Ordinal last_index  = (NPT_Ordinal)(NPT_POINTER_TO_LONG(last-m_Items));
    if (first_index >= m_ItemCount ||
        last_index  >= m_ItemCount ||
        first_index > last_index) {
        return NPT_ERROR_INVALID_PARAMETERS;
    }
    
    NPT_Cardinal interval = last_index-first_index+1;
    NPT_Cardinal shifted = m_ItemCount-last_index-1;
    for (NPT_Ordinal i=first_index; i<first_index+shifted; i++) {
        m_Items[i] = m_Items[i+interval];
    }
    
    for (NPT_Ordinal i=first_index+shifted; i<m_ItemCount; i++) {
        m_Items[i].~T();
    }
    
    m_ItemCount -= interval;
    return NPT_SUCCESS;
}
template <typename T>
NPT_Result
NPT_Array<T>::Insert(Iterator where, const T& item, NPT_Cardinal repeat)
{
    
    NPT_Ordinal where_index = where?((NPT_Ordinal)NPT_POINTER_TO_LONG(where-m_Items)):m_ItemCount;
    if (where > &m_Items[m_ItemCount] || repeat == 0) return NPT_ERROR_INVALID_PARAMETERS;
    NPT_Cardinal needed = m_ItemCount+repeat;
    if (needed > m_Capacity) {
        
        NPT_Cardinal new_capacity;
        T* new_items = Allocate(needed, new_capacity);
        if (new_items == NULL) return NPT_ERROR_OUT_OF_MEMORY;
        m_Capacity = new_capacity;
        
        for (NPT_Ordinal i=0; i<where_index; i++) {
            new((void*)&new_items[i])T(m_Items[i]);
            m_Items[i].~T();
        }
        
        for (NPT_Ordinal i=where_index; i<m_ItemCount; i++) {
            new((void*)&new_items[i+repeat])T(m_Items[i]);
            m_Items[i].~T();
        }
        
        ::operator delete((void*)m_Items);
        m_Items = new_items;
    } else {
        
        for (NPT_Ordinal i=m_ItemCount; i>where_index; i--) {
            new((void*)&m_Items[i+repeat-1])T(m_Items[i-1]);
            m_Items[i-1].~T();
        }
    }
    
    for (NPT_Cardinal i=where_index; i<where_index+repeat; i++) {
        new((void*)&m_Items[i])T(item);
    }
    
    m_ItemCount += repeat;
    return NPT_SUCCESS;
}
template <typename T>
NPT_Result
NPT_Array<T>::Resize(NPT_Cardinal size)
{
    if (size < m_ItemCount) {
        
        for (NPT_Ordinal i=size; i<m_ItemCount; i++) {
            m_Items[i].~T();
        }
        m_ItemCount = size;
    } else if (size > m_ItemCount) {
        return Resize(size, T());
    }
    return NPT_SUCCESS;
}
template <typename T>
NPT_Result
NPT_Array<T>::Resize(NPT_Cardinal size, const T& fill)
{
    if (size < m_ItemCount) {
        return Resize(size);
    } else if (size > m_ItemCount) {
        Reserve(size);
        for (NPT_Ordinal i=m_ItemCount; i<size; i++) {
            new ((void*)&m_Items[i]) T(fill);
        }
        m_ItemCount = size;
    }
    return NPT_SUCCESS;
}
template <typename T>
bool
NPT_Array<T>::Contains(const T& data) const
{
    for (NPT_Ordinal i=0; i<m_ItemCount; i++) {
        if (m_Items[i] == data) return true;
    }
    return false;
}
template <typename T>
bool
NPT_Array<T>::operator==(const NPT_Array<T>& other) const
{
    
    if (other.m_ItemCount != m_ItemCount) return false;
    
    for (NPT_Ordinal i=0; i<m_ItemCount; i++) {
        if (!(m_Items[i] == other.m_Items[i])) return false;
    }
    return true;
}
template <typename T>
inline
bool
NPT_Array<T>::operator!=(const NPT_Array<T>& other) const
{
    return !(*this == other);
}
#endif