Changeset 1328


Ignore:
Timestamp:
May 1, 2012, 8:33:19 PM (9 years ago)
Author:
sam
Message:

core: the Array class now properly works with non-POD types.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/array.h

    r1326 r1328  
    1919#define __LOL_ARRAY_H__
    2020
     21#include <new>
    2122#include <stdint.h>
    2223
     
    2526
    2627/*
    27  * The base array type
    28  * FIXME: only works properly with POD types for now
     28 * The base array type.
     29 *
     30 * Contains an m_data memory array of Elements, of which only the first
     31 * m_count are allocated. The rest is uninitialised memory.
    2932 */
    3033
     
    3437    typedef T Element;
    3538
    36     inline ArrayBase() : m_data(0), m_count(0), m_reserved(0) {}
    37     inline ~ArrayBase() { delete[] m_data; }
     39    inline ArrayBase() : m_data(0), m_count(0), m_reserved(0)
     40    {
     41    }
     42
     43    inline ~ArrayBase()
     44    {
     45        for (int i = 0; i < m_count; i++)
     46            m_data[i].~Element();
     47        delete[] reinterpret_cast<uint8_t *>(m_data);
     48    }
    3849
    3950    ArrayBase(ArrayBase const& that) : m_data(0), m_count(0), m_reserved(0)
    4051    {
    41         Reserve(that.m_reserved);
    42         memcpy(m_data, that.m_data, that.m_count * sizeof(Element));
     52        /* Reserve the exact number of values instead of what the other
     53         * array had reserved. Just a method for not wasting too much. */
     54        Reserve(that.m_count);
     55        for (int i = 0; i < that.m_count; i++)
     56            new(&m_data[i]) Element(that[i]);
    4357        m_count = that.m_count;
    4458    }
     
    4660    ArrayBase& operator=(ArrayBase const& that)
    4761    {
    48         /* FIXME: delete old data!! */
    49         m_data = 0;
    50         m_count = 0;
    51         m_reserved = 0;
    52         Reserve(that.m_reserved);
    53         memcpy(m_data, that.m_data, that.m_count * sizeof(Element));
    54         m_count = that.m_count;
     62        if ((uintptr_t)this != (uintptr_t)&that)
     63        {
     64            if (m_reserved < that.m_count)
     65            {
     66                /* If not enough space, reserve memory and use placement
     67                 * new directly for all elements. */
     68                Reserve(that.m_count);
     69                for (int i = 0; i < that.m_count; i++)
     70                    new(&m_data[i]) Element(that[i]);
     71            }
     72            else
     73            {
     74                /* If enough space, overwrite the common elements, then
     75                 * use placement new for the elements in the other array
     76                 * that we do not have, and finally destroy the remaining
     77                 * elements. */
     78                for (int i = 0; i < m_count && i < that.m_count; i++)
     79                    m_data[i] = Element(that[i]);
     80                for (int i = m_count; i < that.m_count; i++)
     81                    new(&m_data[i]) Element(that[i]);
     82                for (int i = that.m_count; i < m_count; i++)
     83                    m_data[i].~Element();
     84            }
     85            m_count = that.m_count;
     86        }
    5587        return *this;
    5688    }
     
    72104            T tmp = x;
    73105            Reserve(m_count * 13 / 8 + 8);
    74             m_data[m_count++] = tmp;
    75         }
    76         else
    77         {
    78             m_data[m_count++] = x;
     106            new (&m_data[m_count++]) Element(tmp);
     107        }
     108        else
     109        {
     110            new (&m_data[m_count++]) Element(x);
    79111        }
    80112        return *this;
     
    86118    }
    87119
    88     void Remove(int pos)
    89     {
    90         memmove(m_data + pos, m_data + pos + 1, m_count - pos - 1);
    91         m_count--;
    92     }
    93 
    94     void Remove(int pos, int count)
    95     {
    96         memmove(m_data + pos, m_data + pos + count, m_count - pos - count);
    97         m_count -= count;
    98     }
    99 
    100     void Reserve(int count)
    101     {
    102         if (count <= (int)m_reserved)
     120    void Remove(int pos, int todelete = 1)
     121    {
     122        for (int i = pos; i + todelete < m_count; i++)
     123            m_data[i] = m_data[i + todelete];
     124        for (int i = m_count - todelete; i < m_count; i++)
     125            m_data[i].~Element();
     126        m_count -= todelete;
     127    }
     128
     129    void Reserve(int toreserve)
     130    {
     131        if (toreserve <= (int)m_reserved)
    103132            return;
    104133
    105         Element *tmp = new Element[count];
     134        Element *tmp = reinterpret_cast<Element *>
     135                               (new uint8_t [sizeof(Element) * toreserve]);
     136        for (int i = 0; i < m_count; i++)
     137        {
     138            new(&tmp[i]) Element(m_data[i]);
     139            m_data[i].~Element();
     140        }
    106141        if (m_data)
    107         {
    108             memcpy(tmp, m_data, m_count * sizeof(Element));
    109             delete[] m_data;
    110         }
     142            delete[] reinterpret_cast<uint8_t *>(m_data);
    111143        m_data = tmp;
    112         m_reserved = count;
     144        m_reserved = toreserve;
    113145    }
    114146
  • trunk/test/unit/array.cpp

    r1326 r1328  
    5555    }
    5656
     57    LOLUNIT_TEST(ArrayRemove)
     58    {
     59        Array<int> a;
     60        a.Push(0);
     61        a.Push(1);
     62        a.Push(2);
     63        a.Push(3);
     64        a.Remove(1);
     65
     66        LOLUNIT_ASSERT_EQUAL(a[0], 0);
     67        LOLUNIT_ASSERT_EQUAL(a[1], 2);
     68        LOLUNIT_ASSERT_EQUAL(a[2], 3);
     69    }
     70
    5771    LOLUNIT_TEST(EightElements)
    5872    {
Note: See TracChangeset for help on using the changeset viewer.