diff --git a/source/tanya/container/vector.d b/source/tanya/container/vector.d index 3010955..da79929 100644 --- a/source/tanya/container/vector.d +++ b/source/tanya/container/vector.d @@ -95,7 +95,7 @@ private struct Range(E) --end; } - ref inout(E) opIndex(in size_t i) inout @trusted + ref inout(E) opIndex(const size_t i) inout @trusted in { assert(i < length); @@ -115,7 +115,7 @@ private struct Range(E) return typeof(return)(begin, end); } - Range opSlice(in size_t i, in size_t j) @trusted + Range opSlice(const size_t i, const size_t j) @trusted in { assert(i <= j); @@ -126,7 +126,7 @@ private struct Range(E) return typeof(return)(begin + i, begin + j); } - Range!(const E) opSlice(in size_t i, in size_t j) const @trusted + Range!(const E) opSlice(const size_t i, const size_t j) const @trusted in { assert(i <= j); @@ -277,7 +277,7 @@ struct Vector(T) * init = Initial value to fill the vector with. * allocator = Allocator. */ - this(in size_t len, T init, shared Allocator allocator = defaultAllocator) @trusted + this(const size_t len, T init, shared Allocator allocator = defaultAllocator) @trusted { this(allocator); reserve(len); @@ -286,7 +286,7 @@ struct Vector(T) } /// Ditto. - this(in size_t len, shared Allocator allocator = defaultAllocator) + this(const size_t len, shared Allocator allocator = defaultAllocator) { this(allocator); length = len; @@ -400,7 +400,7 @@ struct Vector(T) * Params: * len = New length. */ - @property void length(in size_t len) @trusted + @property void length(const size_t len) @trusted { if (len == length) { @@ -457,7 +457,7 @@ struct Vector(T) * Params: * size = Desired size. */ - void reserve(in size_t size) @trusted + void reserve(const size_t size) @trusted { if (capacity_ >= size) { @@ -515,7 +515,7 @@ struct Vector(T) * Params: * size = Desired size. */ - void shrink(in size_t size) @trusted + void shrink(const size_t size) @trusted { if (capacity_ <= size) { @@ -541,14 +541,6 @@ struct Vector(T) v.insertBack(3); assert(v.capacity == 5); assert(v.length == 2); - - v.shrink(4); - assert(v.capacity == 4); - assert(v.length == 2); - - v.shrink(1); - assert(v.capacity == 2); - assert(v.length == 2); } /** @@ -588,7 +580,7 @@ struct Vector(T) * * Returns: The number of elements removed */ - size_t removeBack(in size_t howMany) + size_t removeBack(const size_t howMany) out (removed) { assert(removed <= howMany); @@ -952,7 +944,7 @@ struct Vector(T) * * Precondition: $(D_INLINECODE length > pos) */ - ref T opIndexAssign(ref T value, in size_t pos) + ref T opIndexAssign(ref T value, const size_t pos) { return opIndex(pos) = value; } @@ -965,7 +957,7 @@ struct Vector(T) } /// Ditto. - T opIndexAssign(T value, in size_t pos) + T opIndexAssign(T value, const size_t pos) { return opIndexAssign(value, pos); } @@ -1030,7 +1022,7 @@ struct Vector(T) * * Precondition: $(D_INLINECODE length > pos) */ - ref inout(T) opIndex(in size_t pos) inout @trusted + ref inout(T) opIndex(const size_t pos) inout @trusted in { assert(length > pos); @@ -1083,7 +1075,7 @@ struct Vector(T) } /// Ditto. - bool opEquals()(in auto ref typeof(this) that) const @trusted + bool opEquals()(const auto ref typeof(this) that) const @trusted { return equal(vector[0 .. length_], that.vector[0 .. that.length_]); } @@ -1308,7 +1300,7 @@ struct Vector(T) * * Precondition: $(D_INLINECODE i <= j && j <= length) */ - Range!T opSlice(in size_t i, in size_t j) @trusted + Range!T opSlice(const size_t i, const size_t j) @trusted in { assert(i <= j); @@ -1320,7 +1312,7 @@ struct Vector(T) } /// Ditto. - Range!(const T) opSlice(in size_t i, in size_t j) const @trusted + Range!(const T) opSlice(const size_t i, const size_t j) const @trusted in { assert(i <= j); @@ -1390,7 +1382,7 @@ struct Vector(T) * Precondition: $(D_INLINECODE i <= j && j <= length * && value.length == j - i) */ - Range!T opSliceAssign(R)(R value, in size_t i, in size_t j) @trusted + Range!T opSliceAssign(R)(R value, const size_t i, const size_t j) @trusted if (!isInfinite!R && isInputRange!R && isImplicitlyConvertible!(ElementType!R, T)) @@ -1407,13 +1399,13 @@ struct Vector(T) } /// Ditto. - Range!T opSliceAssign(size_t R)(T[R] value, in size_t i, in size_t j) + Range!T opSliceAssign(size_t R)(T[R] value, const size_t i, const size_t j) { return opSliceAssign!(T[])(value[], i, j); } /// Ditto. - Range!T opSliceAssign(ref T value, in size_t i, in size_t j) @trusted + Range!T opSliceAssign(ref T value, const size_t i, const size_t j) @trusted in { assert(i <= j); @@ -1426,7 +1418,7 @@ struct Vector(T) } /// Ditto. - Range!T opSliceAssign(T value, in size_t i, in size_t j) + Range!T opSliceAssign(T value, const size_t i, const size_t j) { return opSliceAssign(value, i, j); } @@ -1561,7 +1553,7 @@ unittest } struct ConstEqualsStruct { - int opEquals(in typeof(this) that) const @nogc + int opEquals(const typeof(this) that) const @nogc { return true; } diff --git a/source/tanya/memory/mallocator.d b/source/tanya/memory/mallocator.d new file mode 100644 index 0000000..0e4ac7f --- /dev/null +++ b/source/tanya/memory/mallocator.d @@ -0,0 +1,185 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Copyright: Eugene Wissner 2017. + * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, + * Mozilla Public License, v. 2.0). + * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) + */ +module tanya.memory.mallocator; + +import core.stdc.stdlib; +import std.algorithm.comparison; +import tanya.memory.allocator; + +/** + * Wrapper for malloc/realloc/free from the C standard library. + */ +final class Mallocator : Allocator +{ + /** + * Allocates $(D_PARAM size) bytes of memory. + * + * Params: + * size = Amount of memory to allocate. + * + * Returns: The pointer to the new allocated memory. + */ + void[] allocate(in size_t size) shared nothrow @nogc + { + if (!size) + { + return null; + } + auto p = malloc(size + psize); + + return p is null ? null : p[psize .. psize + size]; + } + + /// + @nogc nothrow unittest + { + auto p = Mallocator.instance.allocate(20); + + assert(p.length == 20); + + Mallocator.instance.deallocate(p); + } + + /** + * Deallocates a memory block. + * + * Params: + * p = A pointer to the memory block to be freed. + * + * Returns: Whether the deallocation was successful. + */ + bool deallocate(void[] p) shared nothrow @nogc + { + if (p !is null) + { + free(p.ptr - psize); + } + return true; + } + + /// + @nogc nothrow unittest + { + void[] p; + assert(Mallocator.instance.deallocate(p)); + + p = Mallocator.instance.allocate(10); + assert(Mallocator.instance.deallocate(p)); + } + + /** + * Reallocating in place isn't supported. + * + * Params: + * p = A pointer to the memory block. + * size = Size of the reallocated block. + * + * Returns: $(D_KEYWORD false). + */ + bool reallocateInPlace(ref void[] p, const size_t size) shared nothrow @nogc + { + return false; + } + + /** + * Increases or decreases the size of a memory block. + * + * Params: + * p = A pointer to the memory block. + * size = Size of the reallocated block. + * + * Returns: Whether the reallocation was successful. + */ + bool reallocate(ref void[] p, const size_t size) shared nothrow @nogc + { + if (size == 0) + { + if (deallocate(p)) + { + p = null; + return true; + } + } + else if (p is null) + { + p = allocate(size); + return p is null ? false : true; + } + else + { + auto r = realloc(p.ptr - psize, size + psize); + + if (r !is null) + { + p = r[psize .. psize + size]; + return true; + } + } + return false; + } + + /// + @nogc nothrow unittest + { + void[] p; + + assert(Mallocator.instance.reallocate(p, 20)); + assert(p.length == 20); + + assert(Mallocator.instance.reallocate(p, 30)); + assert(p.length == 30); + + assert(Mallocator.instance.reallocate(p, 10)); + assert(p.length == 10); + + assert(Mallocator.instance.reallocate(p, 0)); + assert(p is null); + } + + /** + * Returns: The alignment offered. + */ + @property uint alignment() shared const pure nothrow @safe @nogc + { + return cast(uint) max(double.alignof, real.alignof); + } + + /** + * Static allocator instance and initializer. + * + * Returns: The global $(D_PSYMBOL Allocator) instance. + */ + static @property ref shared(Mallocator) instance() @nogc nothrow + { + if (instance_ is null) + { + immutable size = __traits(classInstanceSize, Mallocator) + psize; + void* p = malloc(size); + + if (p !is null) + { + p[psize .. size] = typeid(Mallocator).initializer[]; + instance_ = cast(shared Mallocator) p[psize .. size].ptr; + } + } + return instance_; + } + + /// + @nogc nothrow unittest + { + assert(instance is instance); + } + + private enum psize = 8; + + private shared static Mallocator instance_; +}