Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions src/urt/algorithm.d
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,9 @@ void qsort(alias _pred = void, T)(T[] arr) pure
static int compare(const void* a, const void* b) pure nothrow @nogc
=> pred(*cast(T*)a, *cast(T*)b);

qsort(arr[], T.sizeof, &compare, (void* a, void* b) pure nothrow @nogc {
swap(*cast(T*)a, *cast(T*)b);
});
qsort(arr[], T.sizeof,
(const void* a, const void* b) pure nothrow @nogc => compare(a, b),
(void* a, void* b) pure nothrow @nogc { swap(*cast(T*)a, *cast(T*)b); });
}
else
{
Expand Down Expand Up @@ -213,6 +213,15 @@ void qsort(alias _pred = void, T)(T[] arr) pure
}
}

void qsort(alias _pred = void, T)(T[] arr, scope int delegate(ref T a, ref T b) pure nothrow @nogc pred) pure
{
if (arr.length <= 1)
return;
qsort(arr[], T.sizeof,
cast(int delegate(const void*, const void*) pure nothrow @nogc)pred,
(void* a, void* b) pure nothrow @nogc { swap(*cast(T*)a, *cast(T*)b); });
}

unittest
{
struct S
Expand Down Expand Up @@ -248,6 +257,10 @@ unittest
assert(binary_search!(s => s.x < 30 ? -1 : s.x > 30 ? 1 : 0)(arr2) == 3);
assert(binary_search(arr, 0) == arr.length);

int direction = -1;
qsort(arr, (ref int a, ref int b) => direction*compare(a, b));
assert(arr == [100, 30, 17, 3, -1]);

int[10] rep = [1, 10, 10, 10, 10, 10, 10, 10, 10, 100];
assert(binary_search(rep, 10) == 1);
}
Expand All @@ -260,7 +273,7 @@ version (SmallSize)
// just one generic implementation to minimise the code...
// kinda slow though... look at all those multiplies!
// maybe there's some way to make this faster :/
void qsort(void[] arr, size_t element_size, int function(const void* a, const void* b) pure nothrow @nogc compare, void function(void* a, void* b) pure nothrow @nogc swap) pure
void qsort(void[] arr, size_t element_size, scope int delegate(const void* a, const void* b) pure nothrow @nogc compare, void function(void* a, void* b) pure nothrow @nogc swap) pure
{
void* p = arr.ptr;
size_t length = arr.length / element_size;
Expand Down
71 changes: 58 additions & 13 deletions src/urt/array.d
Original file line number Diff line number Diff line change
Expand Up @@ -622,13 +622,22 @@ nothrow @nogc:
if (is(U : T))
{
assert(pos <= _length, "Insert position out of range");
reserve(_length + 1);
uint old_length = _length++;
move_emplace_overlapping(ptr[pos .. old_length], ptr[pos + 1 .. old_length + 1]);
static if (is(T == class) || is(T == interface))
return (ptr[pos] = item);
static if (is_trivial!T)
{
enum alignment = T.alignof < 4 ? 4 : T.alignof;
enum prefix = T.sizeof < 4 ? 4 : T.sizeof;
T value = item;
ptr = cast(T*)array_insert_trivial(ptr, _length, alloc_count(), cast(uint)pos, &value, T.sizeof, alignment, prefix, has_allocation());
++_length;
return ptr[pos];
}
else
{
reserve(_length + 1);
uint old_length = _length++;
move_emplace_overlapping(ptr[pos .. old_length], ptr[pos + 1 .. old_length + 1]);
return *emplace!T(&ptr[pos], forward!item);
}
}

ref T insertEmplace(Args...)(size_t pos, auto ref Args args)
Expand Down Expand Up @@ -678,9 +687,14 @@ nothrow @nogc:
void remove(size_t i, size_t count = 1)
{
debug assert(i + count <= _length, "Range error");
if (i < _length - count)
move_to!true(ptr[i + count .. _length], ptr[i .. _length - count]);
destroy_all!false(ptr[_length - count .. length]);
static if (is_trivial!T)
array_remove_trivial(ptr, _length, cast(uint)i, cast(uint)count, T.sizeof);
else
{
if (i < _length - count)
move_to!true(ptr[i + count .. _length], ptr[i .. _length - count]);
destroy_all!false(ptr[_length - count .. length]);
}
_length -= cast(uint)count;
}
void remove(const(T)* pItem) { remove(ptr[0 .. _length].indexOfElement(pItem)); }
Expand Down Expand Up @@ -817,6 +831,22 @@ nothrow @nogc:
assert(false, "TODO");
}

package(urt):
void assume_ownership(T* data, uint length)
{
assert(ptr is null && _length == 0);
ptr = data;
_length = length;
}

T* release_ownership()
{
T* data = ptr;
ptr = null;
_length = 0;
return data;
}

private:
uint _length;

Expand Down Expand Up @@ -1050,7 +1080,8 @@ void move_emplace_overlapping(T)(T[] arr, T[] dest)
}
}

pragma(inline, false)
package(urt):

void* array_allocate(uint count, size_t element_size, size_t alignment, size_t prefix) pure
{
void[] mem = .alloc(prefix + element_size * count, alignment);
Expand All @@ -1059,14 +1090,12 @@ void* array_allocate(uint count, size_t element_size, size_t alignment, size_t p
return array;
}

pragma(inline, false)
void array_free(void* ptr, size_t element_size, size_t prefix) pure
{
uint count = (cast(uint*)ptr)[-1];
.free((ptr - prefix)[0 .. prefix + element_size * count]);
}

pragma(inline, false)
void* array_reserve_trivial(void* ptr, uint length, uint count, size_t element_size, size_t alignment, size_t prefix, bool allocated) pure
{
void* result = array_allocate(count, element_size, alignment, prefix);
Expand All @@ -1077,7 +1106,6 @@ void* array_reserve_trivial(void* ptr, uint length, uint count, size_t element_s
return result;
}

pragma(inline, false)
size_t array_growth(size_t capacity, size_t target) pure
{
if (target <= capacity)
Expand All @@ -1091,7 +1119,6 @@ size_t array_growth(size_t capacity, size_t target) pure
return result;
}

pragma(inline, false)
void* array_grow_trivial(void* ptr, uint length, size_t capacity, size_t target, size_t element_size, size_t alignment, size_t prefix, bool allocated) pure
{
size_t count = array_growth(capacity, target);
Expand All @@ -1100,6 +1127,24 @@ void* array_grow_trivial(void* ptr, uint length, size_t capacity, size_t target,
return array_reserve_trivial(ptr, length, cast(uint)count, element_size, alignment, prefix, allocated);
}

void* array_insert_trivial(void* ptr, uint length, size_t capacity, uint pos, const void* value, size_t element_size, size_t alignment, size_t prefix, bool allocated) pure
{
ptr = array_grow_trivial(ptr, length, capacity, length + 1, element_size, alignment, prefix, allocated);
ubyte* bytes = cast(ubyte*)ptr;
if (pos < length)
memmove(bytes + (pos + 1) * element_size, bytes + pos * element_size, (length - pos) * element_size);
memcpy(bytes + pos * element_size, value, element_size);
return ptr;
}

void array_remove_trivial(void* ptr, uint length, uint pos, uint count, size_t element_size) pure
{
if (pos + count < length)
memmove(cast(ubyte*)ptr + pos * element_size, cast(ubyte*)ptr + (pos + count) * element_size, (length - pos - count) * element_size);
}

private:

pragma(inline, true)
bool el_cmp(T)(const T a, const T b)
if (is(T == class) || is(T == interface))
Expand Down
Loading
Loading