Wolfgang Thallergcc16 merge934c3885 months agoHistory
245 lines · 4.9 KB · D
RawDownload
/** * Array container for internal usage. * * Copyright: Copyright Martin Nowak 2013. * License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). * Authors:   Martin Nowak */module core.internal.container.array; static import common = core.internal.container.common; import core.exception : onOutOfMemoryError; struct Array(T){nothrow:    @disable this(this);     ~this()    {        reset();    }     void reset()    {        length = 0;    }     @property size_t length() const    {        return _length;    }     @property void length(size_t nlength)    {        import core.checkedint : mulu;         bool overflow = false;        size_t reqsize = mulu(T.sizeof, nlength, overflow);        if (!overflow)        {            if (nlength < _length)                foreach (ref val; _ptr[nlength .. _length]) common.destroy(val);            _ptr = cast(T*)common.xrealloc(_ptr, reqsize);            if (nlength > _length)                foreach (ref val; _ptr[_length .. nlength]) common.initialize(val);            _length = nlength;        }        else            onOutOfMemoryError();     }     @property bool empty() const    {        return !length;    }     @property ref inout(T) front() inout    in { assert(!empty); }    do    {        return _ptr[0];    }     @property ref inout(T) back() inout    in { assert(!empty); }    do    {        return _ptr[_length - 1];    }     ref inout(T) opIndex(size_t idx) inout    in { assert(idx < length); }    do    {        return _ptr[idx];    }     inout(T)[] opSlice() inout    {        return _ptr[0 .. _length];    }     inout(T)[] opSlice(size_t a, size_t b) inout    in { assert(a < b && b <= length); }    do    {        return _ptr[a .. b];    }     alias opDollar = length;     void insertBack()(auto ref T val)    {        import core.checkedint : addu;         bool overflow = false;        size_t newlength = addu(length, 1, overflow);        if (!overflow)        {            length = newlength;            back = val;        }        else            onOutOfMemoryError();    }     void popBack()    {        length = length - 1;    }     void remove(size_t idx)    in { assert(idx < length); }    do    {        foreach (i; idx .. length - 1)            _ptr[i] = _ptr[i+1];        popBack();    }     void swap(ref Array other)    {        auto ptr = _ptr;        _ptr = other._ptr;        other._ptr = ptr;        immutable len = _length;        _length = other._length;        other._length = len;    }     invariant    {        assert(!_ptr == !_length);    } private:    T* _ptr;    size_t _length;} unittest{    Array!size_t ary;     assert(ary[] == []);    ary.insertBack(5);    assert(ary[] == [5]);    assert(ary[$-1] == 5);    ary.popBack();    assert(ary[] == []);    ary.insertBack(0);    ary.insertBack(1);    assert(ary[] == [0, 1]);    assert(ary[0 .. 1] == [0]);    assert(ary[1 .. 2] == [1]);    assert(ary[$ - 2 .. $] == [0, 1]);    size_t idx;    foreach (val; ary) assert(idx++ == val);    foreach_reverse (val; ary) assert(--idx == val);    foreach (i, val; ary) assert(i == val);    foreach_reverse (i, val; ary) assert(i == val);     ary.insertBack(2);    ary.remove(1);    assert(ary[] == [0, 2]);     assert(!ary.empty);    ary.reset();    assert(ary.empty);    ary.insertBack(0);    assert(!ary.empty);    destroy(ary);    assert(ary.empty);     // not copyable    static assert(!__traits(compiles, { Array!size_t ary2 = ary; }));    Array!size_t ary2;    static assert(!__traits(compiles, ary = ary2));    static void foo(Array!size_t copy) {}    static assert(!__traits(compiles, foo(ary)));     ary2.insertBack(0);    assert(ary.empty);    assert(ary2[] == [0]);    ary.swap(ary2);    assert(ary[] == [0]);    assert(ary2.empty);} unittest{    alias RC = common.RC!();    Array!RC ary;     size_t cnt;    assert(cnt == 0);    ary.insertBack(RC(&cnt));    assert(cnt == 1);    ary.insertBack(RC(&cnt));    assert(cnt == 2);    ary.back = ary.front;    assert(cnt == 2);    ary.popBack();    assert(cnt == 1);    ary.popBack();    assert(cnt == 0);} unittest{    import core.exception;    try    {        // Overflow ary.length.        auto ary = Array!size_t(cast(size_t*)0xdeadbeef, -1);        scope(failure)        {            // prevent destructor from cleaning up invalid memory.            ary._length = 0;            ary._ptr = null;        }         ary.insertBack(0);    }    catch (OutOfMemoryError)    {    }    try    {        // Overflow requested memory size for common.xrealloc().        auto ary = Array!size_t(cast(size_t*)0xdeadbeef, -2);        scope(failure)        {            // prevent destructor from cleaning up invalid memory.            ary._length = 0;            ary._ptr = null;        }        ary.insertBack(0);    }    catch (OutOfMemoryError)    {    }}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t