Array.h

// Array.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2007

#include "Ceda/cxUtils/xvector.h"
#include "Ceda/cxUtils/xostream.h"
#include "Ceda/cxUtils/Archive.h"

// todo: ArchiveCollection.h in turn includes 10 standard library headers like <map>, <list>, <deque> and <set>, 
// this can increase compile times
#include "Ceda/cxUtils/ArchiveCollection.h"

// todo: ListToOStream.h in turn includes 8 standard library headers like <map>, <list>, <deque> and <set>, 
// this can increase compile times
#include "Ceda/cxUtils/ListToOStream.h"

#include <array>

namespace ceda
{
/*
A std::array<T,N> is a fixed size array of N elements of type T.  Use of this template is convenient for two
reasons

1.  It allows for implementing serialise functions to an archive

2.  When a variable of type std::array<T,N> the name of the variable appears to the right of the
    type declaration.  This is convenient for the xcpp code generator
*/

///////////////////////////////////////////////////////////////////////////////////////////////////
// MapArrayType

//      T  -->  typename MapArrayType<T>::type
//
//      T[N] is mapped to std::array<T,N>, any other type is mapped to itself

template <typename T>
struct MapArrayType
{
    typedef T type;
};
template <typename T, size_t N>
struct MapArrayType<T[N]>
{
    typedef std::array<T,N> type;
};

///////////////////////////////////////////////////////////////////////////////////////////////////
// DynArray<T>

/*
Intended for use in ceda data models where the size of the array grows dynamically according
to what is recorded.
*/

template <typename T>
class DynArray
{
public:
    typedef T value_type;

    bool operator<(const DynArray& rhs) const
    {
        ssize_t n1 = m_values.size();
        ssize_t n2 = rhs.m_values.size();
        ssize_t min, max;
        const T* p;
        if (n1 < n2) { min=n1; max=n2; p = rhs.m_values.data(); }
        else         { min=n2; max=n1; p = m_values.data(); }
        for (ssize_t i=0 ; i < min ; ++i)
        {
            if (m_values[i] < rhs.m_values[i]) return true;
            if (m_values[i] != rhs.m_values[i]) return false;
        }
        for (ssize_t i=min ; i < max ; ++i)
        {
            if (p[i] < T()) return true;
            if (p[i] != T()) return false;
        }
        return false;   // equal
    }
    bool operator==(const DynArray& rhs) const 
    { 
        ssize_t n1 = m_values.size();
        ssize_t n2 = rhs.m_values.size();
        ssize_t min, max;
        const T* p;
        if (n1 < n2) { min=n1; max=n2; p = rhs.m_values.data(); }
        else         { min=n2; max=n1; p = m_values.data(); }
        for (ssize_t i=0 ; i < min ; ++i)
        {
            if (m_values[i] != rhs.m_values[i]) return false;
        }
        for (ssize_t i=min ; i < max ; ++i)
        {
            if (p[i] != T()) return false;
        }
        return true;
    }
    bool operator!=(const DynArray& _rhs) const { return !operator==(_rhs); }
    bool operator<=(const DynArray& _rhs) const { return !_rhs.operator<(*this); }
    bool operator>(const DynArray& _rhs) const { return _rhs.operator<(*this); }
    bool operator>=(const DynArray& _rhs) const { return !operator<(_rhs); }
    
    ssize_t size() const { return m_values.size(); }

    const T& operator[](ssize_t i) const
    {
        cxAssert(0 <= i);
        if (i >= m_values.size()) const_cast<DynArray*>(this)->m_values.resize(i+1);
        return m_values[i];
    }
    T& operator[](ssize_t i)
    {
        cxAssert(0 <= i);
        if (i >= m_values.size()) m_values.resize(i+1);
        return m_values[i];
    }

public:
    xvector<T> m_values;
};

template<typename T>
inline xostream& operator<<(xostream& os, const DynArray<T>& x)
{
    os << '[';
    for (ssize_t i=0 ; i < x.m_values.size() ; ++i)
    {
        if (i > 0) os << ',';
        os << x[i];
    }
    os << ']';
    return os;
}

template <typename Archive, typename T> 
inline void Serialise(Archive& ar, const DynArray<T>& x)
{
    ar << x.m_values;
}

template <typename Archive, typename T> 
inline void Deserialise(Archive& ar, DynArray<T>& x)
{
    ar >> x.m_values;
}

} // ceda