view src/basic/SmallArray.d @ 207:e0551773a005

Added the correct version.
author Anders Johnsen <skabet@gmail.com>
date Tue, 12 Aug 2008 18:19:34 +0200
parents d3c148ca429b
children
line wrap: on
line source

module basic.SmallArray;

/**
  This struct acts like a normal dynamic array, with one difference.
  A size is given, which is how many elements are preallocated on the stack.

  Example:
  --------
  SmallArray!(float, 4) array;
  array ~= 1.0;
  array ~= 2.0;
  array ~= 3.0;
  float[] three_floats = array[0 .. 3];
  // The slice gives a reference to the stack, remember to .dup
  array ~= 4.0;
  // not using the heap yet, but after the next line all values will have been
  // copied to the heap.
  array ~= 5.0;
  --------

  Compared to a normal dynamic array there is 8 bytes overhead (on 32 bit cpus)
  and ofcourse size * T.sizeof bytes for the stack allocated array.
 */
struct SmallArray(T, ubyte size = 8)
{
    T[] opSlice(size_t low, size_t high)
    {
        assert(high <= len && low <= high, "Array index out of range");
        return ptr[low .. high];
    }

    T[] opSlice()
    {
        return ptr[0 .. len];
    }
    alias opSlice unsafe;

    T[] safe()
    {
        if (len <= size)
            return static_array[0 .. len].dup;
        return array[0 .. len];
    }

    T[] opSliceAssign(T val, size_t low, size_t high)
    {
        assert(high <= len && low <= high, "Array index out of range");
        return ptr[low .. high] = val;
    }

    T[] opSliceAssign(T val)
    {
        return ptr[0 .. len] = val;
    }

    T opIndex(size_t index)
    {
        assert(index < len, "Array index out of range");
        return ptr[index];
    }

    T opIndexAssign(T val, size_t index)
    {
        assert(index < len, "Array index out of range");
        return ptr[index] = val;
    }

    void opCatAssign(T val)
    {
        if (len < size)
            static_array[len] = val;
        else if (len == size)
        {
            T[] tmp = static_array[].dup;
            array = tmp;
            array ~= val;
        }
        else
            array ~= val;

        ++len;
        if (len <= size)
            ptr = static_array.ptr;
        else
            ptr = array.ptr;
    }
    alias opCatAssign push;

    T pop()
    {
        assert(len > 0, "Can't remove from an empty array");
        return ptr[--len];
    }

    T peek()
    {
        assert(len > 0, "Array is empty");
        return ptr[len - 1];
    }

    size_t length() { return len; }

    static SmallArray opCall()
    {
        SmallArray array;
        array.ptr = array.static_array.ptr;
        return array;
    }

private:
    T* ptr;
    size_t len;
    union
    {
        T[] array;
        T[size] static_array;
    }
}