diff --git a/source/tanya/container/bitvector.d b/source/tanya/container/bitvector.d new file mode 100644 index 0000000..3597a73 --- /dev/null +++ b/source/tanya/container/bitvector.d @@ -0,0 +1,510 @@ +/* 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/. */ + +/** + * Single-dimensioned bit array. + * + * Copyright: Eugene Wissner 2016-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.container.bitvector; + +/** + * Wrapper that allows bit manipulation on $(D_KEYWORD ubyte[]) array. + */ +struct BitVector +{ + protected ubyte[] vector; + + /** + * Params: + * array = Array should be manipulated on. + */ + this(inout(ubyte[]) array) inout pure nothrow @safe @nogc + in + { + assert(array.length <= size_t.max / 8); + assert(array !is null); + } + body + { + vector = array; + } + + /// + unittest + { + ubyte[5] array1 = [234, 3, 252, 10, 18]; + ubyte[3] array2 = [65, 13, 173]; + auto bits = BitVector(array1); + + assert(bits[] is array1); + assert(bits[] !is array2); + + bits = BitVector(array2); + assert(bits[] is array2); + } + + /** + * Returns: Number of bits in the vector. + */ + @property inout(size_t) length() inout const pure nothrow @safe @nogc + { + return vector.length * 8; + } + + /// Ditto. + inout(size_t) opDollar() inout const pure nothrow @safe @nogc + { + return vector.length * 8; + } + + /// + unittest + { + // [01000001, 00001101, 10101101] + ubyte[3] arr = [65, 13, 173]; + auto bits = BitVector(arr); + + assert(bits.length == 24); + } + + /** + * Params: + * bit = Bit position. + * + * Returns: $(D_KEYWORD true) if the bit on position $(D_PARAM bit) is set, + * $(D_KEYWORD false) if not set. + */ + inout(bool) opIndex(size_t bit) inout const pure nothrow @safe @nogc + in + { + assert(bit / 8 <= vector.length); + } + body + { + return (vector[bit / 8] & (0x80 >> (bit % 8))) != 0; + } + + /// + unittest + { + // [01000001, 00001101, 10101101] + ubyte[3] arr = [65, 13, 173]; + auto bits = BitVector(arr); + + assert(!bits[0]); + assert(bits[1]); + assert(bits[7]); + assert(!bits[8]); + assert(!bits[11]); + assert(bits[12]); + assert(bits[20]); + assert(bits[23]); + } + + /** + * Returns: Underlying array. + */ + inout(ubyte[]) opIndex() inout pure nothrow @safe @nogc + { + return vector; + } + + /// + unittest + { + // [01000001, 00001101, 10101101] + ubyte[3] arr = [65, 13, 173]; + auto bits = BitVector(arr); + + assert(bits[] is arr); + } + + /** + * Params: + * value = $(D_KEYWORD true) if the bit should be set, + * $(D_KEYWORD false) if cleared. + * bit = Bit position. + * + * Returns: $(D_PSYMBOL this). + */ + bool opIndexAssign(bool value, size_t bit) pure nothrow @safe @nogc + in + { + assert(bit / 8 <= vector.length); + } + body + { + if (value) + { + vector[bit / 8] |= (0x80 >> (bit % 8)); + } + else + { + vector[bit / 8] &= ~(0x80 >> (bit % 8)); + } + return value; + } + + /// + unittest + { + // [01000001, 00001101, 10101101] + ubyte[3] arr = [65, 13, 173]; + auto bits = BitVector(arr); + + bits[5] = bits[6] = true; + assert(bits[][0] == 71); + + bits[14] = true; + bits[15] = false; + assert(bits[][1] == 14); + + bits[16] = bits[23] = false; + assert(bits[][2] == 44); + } + + /** + * Copies bits from $(D_PARAM vector) into this $(D_PSYMBOL BitVector). + * + * The array that should be assigned, can be smaller (but not larger) than + * the underlying array of this $(D_PSYMBOL BitVector), leading zeros will + * be added in this case to the left. + * + * Params: + * vector = $(D_KEYWORD ubyte[]) array not larger than + * `$(D_PSYMBOL length) / 8`. + * + * Returns: $(D_KEYWORD this). + */ + BitVector opAssign(ubyte[] vector) pure nothrow @safe @nogc + in + { + assert(vector.length <= this.vector.length); + } + body + { + immutable delta = this.vector.length - vector.length; + if (delta > 0) + { + this.vector[0..delta] = 0; + } + this.vector[delta..$] = vector[0..$]; + return this; + } + + /// + unittest + { + ubyte[5] array1 = [234, 3, 252, 10, 18]; + ubyte[3] array2 = [65, 13, 173]; + auto bits = BitVector(array1); + + bits = array2; + assert(bits[][0] == 0); + assert(bits[][1] == 0); + assert(bits[][2] == 65); + assert(bits[][3] == 13); + assert(bits[][4] == 173); + + bits = array2[0..2]; + assert(bits[][0] == 0); + assert(bits[][1] == 0); + assert(bits[][2] == 0); + assert(bits[][3] == 65); + assert(bits[][4] == 13); + } + + /** + * Support for bitwise operations. + * + * Params: + * that = Another bit vector. + * + * Returns: $(D_KEYWORD this). + */ + BitVector opOpAssign(string op)(BitVector that) pure nothrow @safe @nogc + if ((op == "^") || (op == "|") || (op == "&")) + { + return opOpAssign(op)(that.vector); + } + + /// Ditto. + BitVector opOpAssign(string op)(ubyte[] that) pure nothrow @safe @nogc + if ((op == "^") || (op == "|") || (op == "&")) + in + { + assert(that.length <= vector.length); + } + body + { + for (int i = cast(int) vector.length - 1; i >= 0; --i) + { + mixin("vector[i] " ~ op ~ "= " ~ "that[i];"); + } + immutable delta = vector.length - that.length; + if (delta) + { + static if (op == "&") + { + vector[0..delta] = 0; + } + } + return this; + } + + /// + unittest + { + // [01000001, 00001101, 10101101] + ubyte[3] array1 = [65, 13, 173]; + ubyte[3] array2 = [0b01010010, 0b10111110, 0b10111110]; + auto bits = BitVector(array1); + + bits |= array2; + assert(bits[][0] == 0b01010011); + assert(bits[][1] == 0b10111111); + assert(bits[][2] == 0b10111111); + + bits &= array2; + assert(bits[][0] == array2[0]); + assert(bits[][1] == array2[1]); + assert(bits[][2] == array2[2]); + + bits ^= array2; + assert(bits[][0] == 0); + assert(bits[][1] == 0); + assert(bits[][2] == 0); + } + + /** + * Support for shift operations. + * + * Params: + * n = Number of bits. + * + * Returns: $(D_KEYWORD this). + */ + BitVector opOpAssign(string op)(in size_t n) pure nothrow @safe @nogc + if ((op == "<<") || (op == ">>")) + { + if (n >= length) + { + vector[0..$] = 0; + } + else if (n != 0) + { + immutable bit = n % 8, step = n / 8; + immutable delta = 8 - bit; + size_t i, j; + + static if (op == "<<") + { + for (j = step; j < vector.length - 1; ++i) + { + vector[i] = cast(ubyte)((vector[j] << bit) + | vector[++j] >> delta); + } + vector[i] = cast(ubyte)(vector[j] << bit); + vector[$ - step ..$] = 0; + } + else static if (op == ">>") + { + for (i = vector.length - 1, j = i - step; j > 0; --i) + { + vector[i] = cast(ubyte)((vector[j] >> bit) + | vector[--j] << delta); + } + vector[i] = cast(ubyte)(vector[j] >> bit); + vector[0..step] = 0; + } + } + return this; + } + + /// + nothrow @safe @nogc unittest + { + ubyte[4] arr = [0b10111110, 0b11110010, 0b01010010, 0b01010011]; + auto bits = BitVector(arr); + + bits <<= 0; + assert(bits[][0] == 0b10111110 && bits[][1] == 0b11110010 + && bits[][2] == 0b01010010 && bits[][3] == 0b01010011); + + bits <<= 2; + assert(bits[][0] == 0b11111011 && bits[][1] == 0b11001001 + && bits[][2] == 0b01001001 && bits[][3] == 0b01001100); + + bits <<= 4; + assert(bits[][0] == 0b10111100 && bits[][1] == 0b10010100 + && bits[][2] == 0b10010100 && bits[][3] == 0b11000000); + + bits <<= 8; + assert(bits[][0] == 0b10010100 && bits[][1] == 0b10010100 + && bits[][2] == 0b11000000 && bits[][3] == 0b00000000); + + bits <<= 7; + assert(bits[][0] == 0b01001010 && bits[][1] == 0b01100000 + && bits[][2] == 0b00000000 && bits[][3] == 0b00000000); + + bits <<= 25; + assert(bits[][0] == 0b00000000 && bits[][1] == 0b00000000 + && bits[][2] == 0b00000000 && bits[][3] == 0b00000000); + + arr = [0b00110011, 0b11001100, 0b11111111, 0b01010101]; + bits <<= 24; + assert(bits[][0] == 0b01010101 && bits[][1] == 0b00000000 + && bits[][2] == 0b00000000 && bits[][3] == 0b00000000); + + arr[1] = 0b11001100; + arr[2] = 0b11111111; + arr[3] = 0b01010101; + bits <<= 12; + assert(bits[][0] == 0b11001111 && bits[][1] == 0b11110101 + && bits[][2] == 0b01010000 && bits[][3] == 0b00000000); + + bits <<= 100; + assert(bits[][0] == 0b00000000 && bits[][1] == 0b00000000 + && bits[][2] == 0b00000000 && bits[][3] == 0b00000000); + + arr = [0b10111110, 0b11110010, 0b01010010, 0b01010011]; + bits >>= 0; + assert(bits[][0] == 0b10111110 && bits[][1] == 0b11110010 + && bits[][2] == 0b01010010 && bits[][3] == 0b01010011); + + bits >>= 2; + assert(bits[][0] == 0b00101111 && bits[][1] == 0b10111100 + && bits[][2] == 0b10010100 && bits[][3] == 0b10010100); + + bits >>= 4; + assert(bits[][0] == 0b00000010 && bits[][1] == 0b11111011 + && bits[][2] == 0b11001001 && bits[][3] == 0b01001001); + + bits >>= 8; + assert(bits[][0] == 0b00000000 && bits[][1] == 0b00000010 + && bits[][2] == 0b11111011 && bits[][3] == 0b11001001); + + bits >>= 7; + assert(bits[][0] == 0b00000000 && bits[][1] == 0b00000000 + && bits[][2] == 0b00000101 && bits[][3] == 0b11110111); + + bits >>= 25; + assert(bits[][0] == 0b00000000 && bits[][1] == 0b00000000 + && bits[][2] == 0b00000000 && bits[][3] == 0b00000000); + + arr = [0b00110011, 0b11001100, 0b11111111, 0b01010101]; + bits >>= 24; + assert(bits[][0] == 0b00000000 && bits[][1] == 0b00000000 + && bits[][2] == 0b00000000 && bits[][3] == 0b00110011); + + arr[1] = 0b11001100; + arr[2] = 0b11111111; + arr[3] = 0b01010101; + bits >>= 12; + assert(bits[][0] == 0b00000000 && bits[][1] == 0b00000000 + && bits[][2] == 0b00001100 && bits[][3] == 0b11001111); + + bits >>= 100; + assert(bits[][0] == 0b00000000 && bits[][1] == 0b00000000 + && bits[][2] == 0b00000000 && bits[][3] == 0b00000000); + } + + /** + * Negates all bits. + * + * Returns: $(D_KEYWORD this). + */ + BitVector opUnary(string op)() pure nothrow @safe @nogc + if (op == "~") + { + foreach (ref b; vector) + { + b = ~b; + } + return this; + } + + /// + unittest + { + // [01000001, 00001101, 10101101] + ubyte[3] arr = [65, 13, 173]; + auto bits = BitVector(arr); + + ~bits; + assert(bits[][0] == 0b10111110); + assert(bits[][1] == 0b11110010); + assert(bits[][2] == 0b01010010); + } + + /** + * Iterates through all bits. + * + * Params: + * dg = $(D_KEYWORD foreach) delegate. + * + * Returns: By $(D_PARAM dg) returned value. + */ + int opApply(int delegate(size_t, bool) dg) + { + int result; + foreach (i, ref v; vector) + { + foreach (c; 0..8) + { + result = dg(i * 8 + c, (v & (0x80 >> c)) != 0); + if (result) + { + return result; + } + } + } + return result; + } + + /// Ditto. + int opApply(int delegate(bool) dg) + { + int result; + foreach (ref v; vector) + { + foreach (c; 0..8) + { + result = dg((v & (0x80 >> c)) != 0); + if (result) + { + return result; + } + } + } + return result; + } + + /// + unittest + { + ubyte[2] arr = [0b01000001, 0b00001101]; + auto bits = BitVector(arr); + size_t c; + + foreach (i, v; bits) + { + assert(i == c); + if (i == 1 || i == 7 || i == 15 || i == 13 || i == 12) + { + assert(v); + } + else + { + assert(!v); + } + ++c; + } + assert(c == 16); + } +} diff --git a/source/tanya/container/buffer.d b/source/tanya/container/buffer.d index 4d01ad5..9dde930 100644 --- a/source/tanya/container/buffer.d +++ b/source/tanya/container/buffer.d @@ -7,7 +7,7 @@ * 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.container.buffer; import std.traits; @@ -15,23 +15,23 @@ import tanya.memory; version (unittest) { - private int fillBuffer(ubyte[] buffer, - in size_t size, - int start = 0, - int end = 10) @nogc pure nothrow - in - { - assert(start < end); - } - body - { - auto numberRead = end - start; - for (ubyte i; i < numberRead; ++i) - { - buffer[i] = cast(ubyte) (start + i); - } - return numberRead; - } + private int fillBuffer(ubyte[] buffer, + in size_t size, + int start = 0, + int end = 10) @nogc pure nothrow + in + { + assert(start < end); + } + body + { + auto numberRead = end - start; + for (ubyte i; i < numberRead; ++i) + { + buffer[i] = cast(ubyte) (start + i); + } + return numberRead; + } } /** @@ -45,253 +45,253 @@ version (unittest) * of the pended asynchronous call. * * Params: - * T = Buffer type. + * T = Buffer type. */ struct ReadBuffer(T = ubyte) - if (isScalarType!T) + if (isScalarType!T) { - /// Internal buffer. - private T[] buffer_; + /// Internal buffer. + private T[] buffer_; - /// Filled buffer length. - private size_t length_; + /// Filled buffer length. + private size_t length_; - /// Start of available data. - private size_t start; + /// Start of available data. + private size_t start; - /// Last position returned with $(D_KEYWORD []). - private size_t ring; + /// Last position returned with $(D_KEYWORD []). + private size_t ring; - /// Available space. - private immutable size_t minAvailable = 1024; + /// Available space. + private immutable size_t minAvailable = 1024; - /// Size by which the buffer will grow. - private immutable size_t blockSize = 8192; + /// Size by which the buffer will grow. + private immutable size_t blockSize = 8192; - invariant - { - assert(length_ <= buffer_.length); - assert(blockSize > 0); - assert(minAvailable > 0); - } + invariant + { + assert(length_ <= buffer_.length); + assert(blockSize > 0); + assert(minAvailable > 0); + } - /** - * Creates a new read buffer. - * - * Params: - * size = Initial buffer size and the size by which the buffer - * will grow. - * minAvailable = minimal size should be always available to fill. - * So it will reallocate if $(D_INLINECODE - * $(D_PSYMBOL free) < $(D_PARAM minAvailable)). - * allocator = Allocator. - */ - this(in size_t size, - in size_t minAvailable = 1024, - shared Allocator allocator = defaultAllocator) @trusted - { - this(allocator); - this.minAvailable = minAvailable; - this.blockSize = size; - buffer_ = cast(T[]) allocator_.allocate(size * T.sizeof); - } + /** + * Creates a new read buffer. + * + * Params: + * size = Initial buffer size and the size by which the buffer + * will grow. + * minAvailable = minimal size should be always available to fill. + * So it will reallocate if $(D_INLINECODE + * $(D_PSYMBOL free) < $(D_PARAM minAvailable)). + * allocator = Allocator. + */ + this(in size_t size, + in size_t minAvailable = 1024, + shared Allocator allocator = defaultAllocator) @trusted + { + this(allocator); + this.minAvailable = minAvailable; + this.blockSize = size; + buffer_ = cast(T[]) allocator_.allocate(size * T.sizeof); + } - /// Ditto. - this(shared Allocator allocator) - in - { - assert(allocator_ is null); - } - body - { - allocator_ = allocator; - } + /// Ditto. + this(shared Allocator allocator) + in + { + assert(allocator_ is null); + } + body + { + allocator_ = allocator; + } - /** - * Deallocates the internal buffer. - */ - ~this() @trusted - { - allocator.deallocate(buffer_); - } + /** + * Deallocates the internal buffer. + */ + ~this() @trusted + { + allocator.deallocate(buffer_); + } - /// - unittest - { - ReadBuffer!ubyte b; - assert(b.capacity == 0); - assert(b.length == 0); - } + /// + unittest + { + ReadBuffer!ubyte b; + assert(b.capacity == 0); + assert(b.length == 0); + } - /** - * Returns: The size of the internal buffer. - */ - @property size_t capacity() const - { - return buffer_.length; - } + /** + * Returns: The size of the internal buffer. + */ + @property size_t capacity() const + { + return buffer_.length; + } - /** - * Returns: Data size. - */ - @property size_t length() const - { - return length_ - start; - } + /** + * Returns: Data size. + */ + @property size_t length() const + { + return length_ - start; + } - /// Ditto. - alias opDollar = length; + /// Ditto. + alias opDollar = length; - /** - * Clears the buffer. - * - * Returns: $(D_KEYWORD this). - */ - void clear() - { - start = length_ = ring; - } + /** + * Clears the buffer. + * + * Returns: $(D_KEYWORD this). + */ + void clear() + { + start = length_ = ring; + } - /** - * Returns: Available space. - */ - @property size_t free() const - { - return length > ring ? capacity - length : capacity - ring; - } + /** + * Returns: Available space. + */ + @property size_t free() const + { + return length > ring ? capacity - length : capacity - ring; + } - /// - unittest - { - ReadBuffer!ubyte b; - size_t numberRead; + /// + unittest + { + ReadBuffer!ubyte b; + size_t numberRead; - assert(b.free == 0); + assert(b.free == 0); - // Fills the buffer with values 0..10 - numberRead = fillBuffer(b[], b.free, 0, 10); - b += numberRead; - assert(b.free == b.blockSize - numberRead); - b.clear(); - assert(b.free == b.blockSize); - } + // Fills the buffer with values 0..10 + numberRead = fillBuffer(b[], b.free, 0, 10); + b += numberRead; + assert(b.free == b.blockSize - numberRead); + b.clear(); + assert(b.free == b.blockSize); + } - /** - * Appends some data to the buffer. - * - * Params: - * length = Number of the bytes read. - * - * Returns: $(D_KEYWORD this). - */ - ref ReadBuffer opOpAssign(string op)(in size_t length) - if (op == "+") - { - length_ += length; - ring = start; - return this; - } + /** + * Appends some data to the buffer. + * + * Params: + * length = Number of the bytes read. + * + * Returns: $(D_KEYWORD this). + */ + ref ReadBuffer opOpAssign(string op)(in size_t length) + if (op == "+") + { + length_ += length; + ring = start; + return this; + } - /// - unittest - { - ReadBuffer!ubyte b; - size_t numberRead; - ubyte[] result; + /// + unittest + { + ReadBuffer!ubyte b; + size_t numberRead; + ubyte[] result; - // Fills the buffer with values 0..10 - numberRead = fillBuffer(b[], b.free, 0, 10); - b += numberRead; + // Fills the buffer with values 0..10 + numberRead = fillBuffer(b[], b.free, 0, 10); + b += numberRead; - result = b[0 .. $]; - assert(result[0] == 0); - assert(result[1] == 1); - assert(result[9] == 9); - b.clear(); + result = b[0 .. $]; + assert(result[0] == 0); + assert(result[1] == 1); + assert(result[9] == 9); + b.clear(); - // It shouldn't overwrite, but append another 5 bytes to the buffer - numberRead = fillBuffer(b[], b.free, 0, 10); - b += numberRead; + // It shouldn't overwrite, but append another 5 bytes to the buffer + numberRead = fillBuffer(b[], b.free, 0, 10); + b += numberRead; - numberRead = fillBuffer(b[], b.free, 20, 25); - b += numberRead; + numberRead = fillBuffer(b[], b.free, 20, 25); + b += numberRead; - result = b[0..$]; - assert(result[0] == 0); - assert(result[1] == 1); - assert(result[9] == 9); - assert(result[10] == 20); - assert(result[14] == 24); - } + result = b[0..$]; + assert(result[0] == 0); + assert(result[1] == 1); + assert(result[9] == 9); + assert(result[10] == 20); + assert(result[14] == 24); + } - /** - * Params: - * start = Start position. - * end = End position. - * - * Returns: Array between $(D_PARAM start) and $(D_PARAM end). - */ - T[] opSlice(in size_t start, in size_t end) - { - return buffer_[this.start + start .. this.start + end]; - } + /** + * Params: + * start = Start position. + * end = End position. + * + * Returns: Array between $(D_PARAM start) and $(D_PARAM end). + */ + T[] opSlice(in size_t start, in size_t end) + { + return buffer_[this.start + start .. this.start + end]; + } - /** - * Returns a free chunk of the buffer. - * - * Add ($(D_KEYWORD +=)) the number of the read bytes after using it. - * - * Returns: A free chunk of the buffer. - */ - T[] opIndex() - { - if (start > 0) - { - auto ret = buffer_[0 .. start]; - ring = 0; - return ret; - } - else - { - if (capacity - length < minAvailable) - { - void[] buf = buffer_; - immutable cap = capacity; - () @trusted { - allocator.reallocate(buf, (cap + blockSize) * T.sizeof); - buffer_ = cast(T[]) buf; - }(); - } - ring = length_; - return buffer_[length_ .. $]; - } - } + /** + * Returns a free chunk of the buffer. + * + * Add ($(D_KEYWORD +=)) the number of the read bytes after using it. + * + * Returns: A free chunk of the buffer. + */ + T[] opIndex() + { + if (start > 0) + { + auto ret = buffer_[0 .. start]; + ring = 0; + return ret; + } + else + { + if (capacity - length < minAvailable) + { + void[] buf = buffer_; + immutable cap = capacity; + () @trusted { + allocator.reallocate(buf, (cap + blockSize) * T.sizeof); + buffer_ = cast(T[]) buf; + }(); + } + ring = length_; + return buffer_[length_ .. $]; + } + } - /// - unittest - { - ReadBuffer!ubyte b; - size_t numberRead; - ubyte[] result; + /// + unittest + { + ReadBuffer!ubyte b; + size_t numberRead; + ubyte[] result; - // Fills the buffer with values 0..10 - numberRead = fillBuffer(b[], b.free, 0, 10); - b += numberRead; + // Fills the buffer with values 0..10 + numberRead = fillBuffer(b[], b.free, 0, 10); + b += numberRead; - assert(b.length == 10); - result = b[0 .. $]; - assert(result[0] == 0); - assert(result[9] == 9); - b.clear(); - assert(b.length == 0); - } + assert(b.length == 10); + result = b[0 .. $]; + assert(result[0] == 0); + assert(result[9] == 9); + b.clear(); + assert(b.length == 0); + } - mixin DefaultAllocator; + mixin DefaultAllocator; } private unittest { - static assert(is(ReadBuffer!int)); + static assert(is(ReadBuffer!int)); } /** @@ -304,385 +304,385 @@ private unittest * reading, because it may allocate and move elements. * * Params: - * T = Buffer type. + * T = Buffer type. */ struct WriteBuffer(T = ubyte) - if (isScalarType!T) + if (isScalarType!T) { - /// Internal buffer. - private T[] buffer_; + /// Internal buffer. + private T[] buffer_; - /// Buffer start position. - private size_t start; + /// Buffer start position. + private size_t start; - /// Buffer ring area size. After this position begins buffer overflow area. - private size_t ring; + /// Buffer ring area size. After this position begins buffer overflow area. + private size_t ring; - /// Size by which the buffer will grow. - private immutable size_t blockSize; + /// Size by which the buffer will grow. + private immutable size_t blockSize; - /// The position of the free area in the buffer. - private size_t position; + /// The position of the free area in the buffer. + private size_t position; - invariant - { - assert(blockSize > 0); - // Position can refer to an element outside the buffer if the buffer is full. - assert(position <= buffer_.length); - } + invariant + { + assert(blockSize > 0); + // Position can refer to an element outside the buffer if the buffer is full. + assert(position <= buffer_.length); + } - /** - * Params: - * size = Initial buffer size and the size by which the buffer will - * grow. - * allocator = Allocator. - * - * Precondition: $(D_INLINECODE size > 0 && allocator !is null) - */ - this(in size_t size, shared Allocator allocator = defaultAllocator) @trusted - in - { - assert(size > 0); - assert(allocator !is null); - } - body - { - blockSize = size; - ring = size - 1; - allocator_ = allocator; - buffer_ = cast(T[]) allocator_.allocate(size * T.sizeof); - } + /** + * Params: + * size = Initial buffer size and the size by which the buffer will + * grow. + * allocator = Allocator. + * + * Precondition: $(D_INLINECODE size > 0 && allocator !is null) + */ + this(in size_t size, shared Allocator allocator = defaultAllocator) @trusted + in + { + assert(size > 0); + assert(allocator !is null); + } + body + { + blockSize = size; + ring = size - 1; + allocator_ = allocator; + buffer_ = cast(T[]) allocator_.allocate(size * T.sizeof); + } - @disable this(); + @disable this(); - /** - * Deallocates the internal buffer. - */ - ~this() - { - allocator.deallocate(buffer_); - } + /** + * Deallocates the internal buffer. + */ + ~this() + { + allocator.deallocate(buffer_); + } - /** - * Returns: The size of the internal buffer. - */ - @property size_t capacity() const - { - return buffer_.length; - } + /** + * Returns: The size of the internal buffer. + */ + @property size_t capacity() const + { + return buffer_.length; + } - /** - * Note that $(D_PSYMBOL length) doesn't return the real length of the data, - * but only the array length that will be returned with $(D_PSYMBOL opIndex) - * next time. Be sure to call $(D_PSYMBOL opIndex) and set $(D_KEYWORD +=) - * until $(D_PSYMBOL length) returns 0. - * - * Returns: Data size. - */ - @property size_t length() const - { - if (position > ring || position < start) // Buffer overflowed - { - return ring - start + 1; - } - else - { - return position - start; - } - } + /** + * Note that $(D_PSYMBOL length) doesn't return the real length of the data, + * but only the array length that will be returned with $(D_PSYMBOL opIndex) + * next time. Be sure to call $(D_PSYMBOL opIndex) and set $(D_KEYWORD +=) + * until $(D_PSYMBOL length) returns 0. + * + * Returns: Data size. + */ + @property size_t length() const + { + if (position > ring || position < start) // Buffer overflowed + { + return ring - start + 1; + } + else + { + return position - start; + } + } - /// Ditto. - alias opDollar = length; + /// Ditto. + alias opDollar = length; - /// - unittest - { - auto b = WriteBuffer!ubyte(4); - ubyte[3] buf = [48, 23, 255]; + /// + unittest + { + auto b = WriteBuffer!ubyte(4); + ubyte[3] buf = [48, 23, 255]; - b ~= buf; - assert(b.length == 3); - b += 2; - assert(b.length == 1); + b ~= buf; + assert(b.length == 3); + b += 2; + assert(b.length == 1); - b ~= buf; - assert(b.length == 2); - b += 2; - assert(b.length == 2); + b ~= buf; + assert(b.length == 2); + b += 2; + assert(b.length == 2); - b ~= buf; - assert(b.length == 5); - b += b.length; - assert(b.length == 0); - } + b ~= buf; + assert(b.length == 5); + b += b.length; + assert(b.length == 0); + } - /** - * Returns: Available space. - */ - @property size_t free() const - { - return capacity - length; - } + /** + * Returns: Available space. + */ + @property size_t free() const + { + return capacity - length; + } - /** - * Appends data to the buffer. - * - * Params: - * buffer = Buffer chunk got with $(D_PSYMBOL opIndex). - */ - ref WriteBuffer opOpAssign(string op)(in T[] buffer) - if (op == "~") - { - size_t end, start; + /** + * Appends data to the buffer. + * + * Params: + * buffer = Buffer chunk got with $(D_PSYMBOL opIndex). + */ + ref WriteBuffer opOpAssign(string op)(in T[] buffer) + if (op == "~") + { + size_t end, start; - if (position >= this.start && position <= ring) - { - auto afterRing = ring + 1; + if (position >= this.start && position <= ring) + { + auto afterRing = ring + 1; - end = position + buffer.length; - if (end > afterRing) - { - end = afterRing; - } - start = end - position; - buffer_[position .. end] = buffer[0 .. start]; - if (end == afterRing) - { - position = this.start == 0 ? afterRing : 0; - } - else - { - position = end; - } - } + end = position + buffer.length; + if (end > afterRing) + { + end = afterRing; + } + start = end - position; + buffer_[position .. end] = buffer[0 .. start]; + if (end == afterRing) + { + position = this.start == 0 ? afterRing : 0; + } + else + { + position = end; + } + } - // Check if we have some free space at the beginning - if (start < buffer.length && position < this.start) - { - end = position + buffer.length - start; - if (end > this.start) - { - end = this.start; - } - auto areaEnd = end - position + start; - buffer_[position .. end] = buffer[start .. areaEnd]; - position = end == this.start ? ring + 1 : end - position; - start = areaEnd; - } + // Check if we have some free space at the beginning + if (start < buffer.length && position < this.start) + { + end = position + buffer.length - start; + if (end > this.start) + { + end = this.start; + } + auto areaEnd = end - position + start; + buffer_[position .. end] = buffer[start .. areaEnd]; + position = end == this.start ? ring + 1 : end - position; + start = areaEnd; + } - // And if we still haven't found any place, save the rest in the overflow area - if (start < buffer.length) - { - end = position + buffer.length - start; - if (end > capacity) - { - auto newSize = (end / blockSize * blockSize + blockSize) * T.sizeof; - () @trusted { - void[] buf = buffer_; - allocator.reallocate(buf, newSize); - buffer_ = cast(T[]) buf; - }(); - } - buffer_[position .. end] = buffer[start .. $]; - position = end; - if (this.start == 0) - { - ring = capacity - 1; - } - } + // And if we still haven't found any place, save the rest in the overflow area + if (start < buffer.length) + { + end = position + buffer.length - start; + if (end > capacity) + { + auto newSize = (end / blockSize * blockSize + blockSize) * T.sizeof; + () @trusted { + void[] buf = buffer_; + allocator.reallocate(buf, newSize); + buffer_ = cast(T[]) buf; + }(); + } + buffer_[position .. end] = buffer[start .. $]; + position = end; + if (this.start == 0) + { + ring = capacity - 1; + } + } - return this; - } + return this; + } - /// - unittest - { - auto b = WriteBuffer!ubyte(4); - ubyte[3] buf = [48, 23, 255]; + /// + unittest + { + auto b = WriteBuffer!ubyte(4); + ubyte[3] buf = [48, 23, 255]; - b ~= buf; - assert(b.capacity == 4); - assert(b.buffer_[0] == 48 && b.buffer_[1] == 23 && b.buffer_[2] == 255); + b ~= buf; + assert(b.capacity == 4); + assert(b.buffer_[0] == 48 && b.buffer_[1] == 23 && b.buffer_[2] == 255); - b += 2; - b ~= buf; - assert(b.capacity == 4); - assert(b.buffer_[0] == 23 && b.buffer_[1] == 255 - && b.buffer_[2] == 255 && b.buffer_[3] == 48); + b += 2; + b ~= buf; + assert(b.capacity == 4); + assert(b.buffer_[0] == 23 && b.buffer_[1] == 255 + && b.buffer_[2] == 255 && b.buffer_[3] == 48); - b += 2; - b ~= buf; - assert(b.capacity == 8); - assert(b.buffer_[0] == 23 && b.buffer_[1] == 255 - && b.buffer_[2] == 48 && b.buffer_[3] == 23 && b.buffer_[4] == 255); - } + b += 2; + b ~= buf; + assert(b.capacity == 8); + assert(b.buffer_[0] == 23 && b.buffer_[1] == 255 + && b.buffer_[2] == 48 && b.buffer_[3] == 23 && b.buffer_[4] == 255); + } - /// - unittest - { - auto b = WriteBuffer!ubyte(2); - ubyte[3] buf = [48, 23, 255]; + /// + unittest + { + auto b = WriteBuffer!ubyte(2); + ubyte[3] buf = [48, 23, 255]; - b ~= buf; - assert(b.start == 0); - assert(b.capacity == 4); - assert(b.ring == 3); - assert(b.position == 3); - } + b ~= buf; + assert(b.start == 0); + assert(b.capacity == 4); + assert(b.ring == 3); + assert(b.position == 3); + } - /** - * Sets how many bytes were written. It will shrink the buffer - * appropriately. Always call it after $(D_PSYMBOL opIndex). - * - * Params: - * length = Length of the written data. - * - * Returns: $(D_KEYWORD this). - */ - ref WriteBuffer opOpAssign(string op)(in size_t length) - if (op == "+") - in - { - assert(length <= this.length); - } - body - { - auto afterRing = ring + 1; - auto oldStart = start; + /** + * Sets how many bytes were written. It will shrink the buffer + * appropriately. Always call it after $(D_PSYMBOL opIndex). + * + * Params: + * length = Length of the written data. + * + * Returns: $(D_KEYWORD this). + */ + ref WriteBuffer opOpAssign(string op)(in size_t length) + if (op == "+") + in + { + assert(length <= this.length); + } + body + { + auto afterRing = ring + 1; + auto oldStart = start; - if (length <= 0) - { - return this; - } - else if (position <= afterRing) - { - start += length; - if (start > 0 && position == afterRing) - { - position = oldStart; - } - } - else - { - auto overflow = position - afterRing; + if (length <= 0) + { + return this; + } + else if (position <= afterRing) + { + start += length; + if (start > 0 && position == afterRing) + { + position = oldStart; + } + } + else + { + auto overflow = position - afterRing; - if (overflow > length) - { - immutable afterLength = afterRing + length; - buffer_[start .. start + length] = buffer_[afterRing .. afterLength]; - buffer_[afterRing .. afterLength] = buffer_[afterLength .. position]; - position -= length; - } - else if (overflow == length) - { - buffer_[start .. start + overflow] = buffer_[afterRing .. position]; - position -= overflow; - } - else - { - buffer_[start .. start + overflow] = buffer_[afterRing .. position]; - position = overflow; - } - start += length; + if (overflow > length) + { + immutable afterLength = afterRing + length; + buffer_[start .. start + length] = buffer_[afterRing .. afterLength]; + buffer_[afterRing .. afterLength] = buffer_[afterLength .. position]; + position -= length; + } + else if (overflow == length) + { + buffer_[start .. start + overflow] = buffer_[afterRing .. position]; + position -= overflow; + } + else + { + buffer_[start .. start + overflow] = buffer_[afterRing .. position]; + position = overflow; + } + start += length; - if (start == position) - { - if (position != afterRing) - { - position = 0; - } - start = 0; - ring = capacity - 1; - } - } - if (start > ring) - { - start = 0; - } - return this; - } + if (start == position) + { + if (position != afterRing) + { + position = 0; + } + start = 0; + ring = capacity - 1; + } + } + if (start > ring) + { + start = 0; + } + return this; + } - /// - unittest - { - auto b = WriteBuffer!ubyte(6); - ubyte[6] buf = [23, 23, 255, 128, 127, 9]; + /// + unittest + { + auto b = WriteBuffer!ubyte(6); + ubyte[6] buf = [23, 23, 255, 128, 127, 9]; - b ~= buf; - assert(b.length == 6); - b += 2; - assert(b.length == 4); - b += 4; - assert(b.length == 0); - } + b ~= buf; + assert(b.length == 6); + b += 2; + assert(b.length == 4); + b += 4; + assert(b.length == 0); + } - /** - * Returns a chunk with data. - * - * After calling it, set $(D_KEYWORD +=) to the length could be - * written. - * - * $(D_PSYMBOL opIndex) may return only part of the data. You may need - * to call it and set $(D_KEYWORD +=) several times until - * $(D_PSYMBOL length) is 0. If all the data can be written, - * maximally 3 calls are required. - * - * Returns: A chunk of data buffer. - */ - T[] opSlice(in size_t start, in size_t end) - { - immutable internStart = this.start + start; + /** + * Returns a chunk with data. + * + * After calling it, set $(D_KEYWORD +=) to the length could be + * written. + * + * $(D_PSYMBOL opIndex) may return only part of the data. You may need + * to call it and set $(D_KEYWORD +=) several times until + * $(D_PSYMBOL length) is 0. If all the data can be written, + * maximally 3 calls are required. + * + * Returns: A chunk of data buffer. + */ + T[] opSlice(in size_t start, in size_t end) + { + immutable internStart = this.start + start; - if (position > ring || position < start) // Buffer overflowed - { - return buffer_[this.start .. ring + 1 - length + end]; - } - else - { - return buffer_[this.start .. this.start + end]; - } - } + if (position > ring || position < start) // Buffer overflowed + { + return buffer_[this.start .. ring + 1 - length + end]; + } + else + { + return buffer_[this.start .. this.start + end]; + } + } - /// - unittest - { - auto b = WriteBuffer!ubyte(6); - ubyte[6] buf = [23, 23, 255, 128, 127, 9]; + /// + unittest + { + auto b = WriteBuffer!ubyte(6); + ubyte[6] buf = [23, 23, 255, 128, 127, 9]; - b ~= buf; - assert(b[0 .. $] == buf[0 .. 6]); - b += 2; + b ~= buf; + assert(b[0 .. $] == buf[0 .. 6]); + b += 2; - assert(b[0 .. $] == buf[2 .. 6]); + assert(b[0 .. $] == buf[2 .. 6]); - b ~= buf; - assert(b[0 .. $] == buf[2 .. 6]); - b += b.length; + b ~= buf; + assert(b[0 .. $] == buf[2 .. 6]); + b += b.length; - assert(b[0 .. $] == buf[0 .. 6]); - b += b.length; - } + assert(b[0 .. $] == buf[0 .. 6]); + b += b.length; + } - /** - * After calling it, set $(D_KEYWORD +=) to the length could be - * written. - * - * $(D_PSYMBOL opIndex) may return only part of the data. You may need - * to call it and set $(D_KEYWORD +=) several times until - * $(D_PSYMBOL length) is 0. If all the data can be written, - * maximally 3 calls are required. - * - * Returns: A chunk of data buffer. - */ - T[] opIndex() - { - return opSlice(0, length); - } + /** + * After calling it, set $(D_KEYWORD +=) to the length could be + * written. + * + * $(D_PSYMBOL opIndex) may return only part of the data. You may need + * to call it and set $(D_KEYWORD +=) several times until + * $(D_PSYMBOL length) is 0. If all the data can be written, + * maximally 3 calls are required. + * + * Returns: A chunk of data buffer. + */ + T[] opIndex() + { + return opSlice(0, length); + } - mixin DefaultAllocator; + mixin DefaultAllocator; } private unittest { - static assert(is(typeof(WriteBuffer!int(5)))); + static assert(is(typeof(WriteBuffer!int(5)))); } diff --git a/source/tanya/container/entry.d b/source/tanya/container/entry.d index 1194f6b..cc74204 100644 --- a/source/tanya/container/entry.d +++ b/source/tanya/container/entry.d @@ -9,14 +9,14 @@ * 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.container.entry; package struct SEntry(T) { - /// Item content. - T content; + /// Item content. + T content; - /// Next item. - SEntry* next; + /// Next item. + SEntry* next; } diff --git a/source/tanya/container/package.d b/source/tanya/container/package.d index db8f025..7ba9f20 100644 --- a/source/tanya/container/package.d +++ b/source/tanya/container/package.d @@ -3,13 +3,16 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** + * Abstract data types whose instances are collections of other objects. + * * Copyright: Eugene Wissner 2016-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.container; +public import tanya.container.bitvector; public import tanya.container.buffer; public import tanya.container.list; public import tanya.container.vector; diff --git a/source/tanya/container/queue.d b/source/tanya/container/queue.d index 6388013..48cc483 100644 --- a/source/tanya/container/queue.d +++ b/source/tanya/container/queue.d @@ -3,11 +3,13 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** + * FIFO queue. + * * Copyright: Eugene Wissner 2016-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.container.queue; import core.exception; @@ -20,267 +22,267 @@ import tanya.memory; * FIFO queue. * * Params: - * T = Content type. + * T = Content type. */ struct Queue(T) { - /** - * Removes all elements from the queue. - */ - ~this() - { - while (!empty) - { - dequeue(); - } - } + /** + * Removes all elements from the queue. + */ + ~this() + { + while (!empty) + { + dequeue(); + } + } - /** - * Returns how many elements are in the queue. It iterates through the queue - * to count the elements. - * - * Returns: How many elements are in the queue. - */ - size_t length() const - { - size_t len; - for (const(SEntry!T)* i = first; i !is null; i = i.next) - { - ++len; - } - return len; - } + /** + * Returns how many elements are in the queue. It iterates through the queue + * to count the elements. + * + * Returns: How many elements are in the queue. + */ + size_t length() const + { + size_t len; + for (const(SEntry!T)* i = first; i !is null; i = i.next) + { + ++len; + } + return len; + } - /// - unittest - { - Queue!int q; + /// + unittest + { + Queue!int q; - assert(q.length == 0); - q.enqueue(5); - assert(q.length == 1); - q.enqueue(4); - assert(q.length == 2); - q.enqueue(9); - assert(q.length == 3); + assert(q.length == 0); + q.enqueue(5); + assert(q.length == 1); + q.enqueue(4); + assert(q.length == 2); + q.enqueue(9); + assert(q.length == 3); - q.dequeue(); - assert(q.length == 2); - q.dequeue(); - assert(q.length == 1); - q.dequeue(); - assert(q.length == 0); - } + q.dequeue(); + assert(q.length == 2); + q.dequeue(); + assert(q.length == 1); + q.dequeue(); + assert(q.length == 0); + } - private void enqueueEntry(ref SEntry!T* entry) - { - if (empty) - { - first = rear = entry; - } - else - { - rear.next = entry; - rear = rear.next; - } - } + private void enqueueEntry(ref SEntry!T* entry) + { + if (empty) + { + first = rear = entry; + } + else + { + rear.next = entry; + rear = rear.next; + } + } - private SEntry!T* allocateEntry() - { - auto temp = cast(SEntry!T*) allocator.allocate(SEntry!T.sizeof); - if (temp is null) - { - onOutOfMemoryError(); - } - return temp; - } + private SEntry!T* allocateEntry() + { + auto temp = cast(SEntry!T*) allocator.allocate(SEntry!T.sizeof); + if (temp is null) + { + onOutOfMemoryError(); + } + return temp; + } - /** - * Inserts a new element. - * - * Params: - * x = New element. - */ - void enqueue(ref T x) - { - auto temp = allocateEntry(); + /** + * Inserts a new element. + * + * Params: + * x = New element. + */ + void enqueue(ref T x) + { + auto temp = allocateEntry(); - *temp = SEntry!T.init; - temp.content = x; + *temp = SEntry!T.init; + temp.content = x; - enqueueEntry(temp); - } + enqueueEntry(temp); + } - /// Ditto. - void enqueue(T x) - { - auto temp = allocateEntry(); + /// Ditto. + void enqueue(T x) + { + auto temp = allocateEntry(); - moveEmplace(x, (*temp).content); - (*temp).next = null; + moveEmplace(x, (*temp).content); + (*temp).next = null; - enqueueEntry(temp); - } + enqueueEntry(temp); + } - /// - unittest - { - Queue!int q; + /// + unittest + { + Queue!int q; - assert(q.empty); - q.enqueue(8); - q.enqueue(9); - assert(q.dequeue() == 8); - assert(q.dequeue() == 9); - } + assert(q.empty); + q.enqueue(8); + q.enqueue(9); + assert(q.dequeue() == 8); + assert(q.dequeue() == 9); + } - /** - * Returns: $(D_KEYWORD true) if the queue is empty. - */ - @property bool empty() const - { - return first is null; - } + /** + * Returns: $(D_KEYWORD true) if the queue is empty. + */ + @property bool empty() const + { + return first is null; + } - /// - unittest - { - Queue!int q; - int value = 7; + /// + unittest + { + Queue!int q; + int value = 7; - assert(q.empty); - q.enqueue(value); - assert(!q.empty); - } + assert(q.empty); + q.enqueue(value); + assert(!q.empty); + } - /** - * Move the position to the next element. - * - * Returns: Dequeued element. - */ - T dequeue() - in - { - assert(!empty); - } - body - { - auto n = first.next; - T ret = move(first.content); + /** + * Move the position to the next element. + * + * Returns: Dequeued element. + */ + T dequeue() + in + { + assert(!empty); + } + body + { + auto n = first.next; + T ret = move(first.content); - allocator.dispose(first); - first = n; - return ret; - } + allocator.dispose(first); + first = n; + return ret; + } - /// - unittest - { - Queue!int q; + /// + unittest + { + Queue!int q; - q.enqueue(8); - q.enqueue(9); - assert(q.dequeue() == 8); - assert(q.dequeue() == 9); - } + q.enqueue(8); + q.enqueue(9); + assert(q.dequeue() == 8); + assert(q.dequeue() == 9); + } - /** - * $(D_KEYWORD foreach) iteration. The elements will be automatically - * dequeued. - * - * Params: - * dg = $(D_KEYWORD foreach) body. - * - * Returns: The value returned from $(D_PARAM dg). - */ - int opApply(scope int delegate(ref size_t i, ref T) @nogc dg) - { - int result; + /** + * $(D_KEYWORD foreach) iteration. The elements will be automatically + * dequeued. + * + * Params: + * dg = $(D_KEYWORD foreach) body. + * + * Returns: The value returned from $(D_PARAM dg). + */ + int opApply(scope int delegate(ref size_t i, ref T) @nogc dg) + { + int result; - for (size_t i = 0; !empty; ++i) - { - auto e = dequeue(); - if ((result = dg(i, e)) != 0) - { - return result; - } - } - return result; - } + for (size_t i = 0; !empty; ++i) + { + auto e = dequeue(); + if ((result = dg(i, e)) != 0) + { + return result; + } + } + return result; + } - /// Ditto. - int opApply(scope int delegate(ref T) @nogc dg) - { - int result; + /// Ditto. + int opApply(scope int delegate(ref T) @nogc dg) + { + int result; - while (!empty) - { - auto e = dequeue(); - if ((result = dg(e)) != 0) - { - return result; - } - } - return result; - } + while (!empty) + { + auto e = dequeue(); + if ((result = dg(e)) != 0) + { + return result; + } + } + return result; + } - /// - unittest - { - Queue!int q; + /// + unittest + { + Queue!int q; - size_t j; - q.enqueue(5); - q.enqueue(4); - q.enqueue(9); - foreach (i, e; q) - { - assert(i != 2 || e == 9); - assert(i != 1 || e == 4); - assert(i != 0 || e == 5); - ++j; - } - assert(j == 3); - assert(q.empty); + size_t j; + q.enqueue(5); + q.enqueue(4); + q.enqueue(9); + foreach (i, e; q) + { + assert(i != 2 || e == 9); + assert(i != 1 || e == 4); + assert(i != 0 || e == 5); + ++j; + } + assert(j == 3); + assert(q.empty); - j = 0; - q.enqueue(5); - q.enqueue(4); - q.enqueue(9); - foreach (e; q) - { - assert(j != 2 || e == 9); - assert(j != 1 || e == 4); - assert(j != 0 || e == 5); - ++j; - } - assert(j == 3); - assert(q.empty); - } + j = 0; + q.enqueue(5); + q.enqueue(4); + q.enqueue(9); + foreach (e; q) + { + assert(j != 2 || e == 9); + assert(j != 1 || e == 4); + assert(j != 0 || e == 5); + ++j; + } + assert(j == 3); + assert(q.empty); + } - private SEntry!T* first; - private SEntry!T* rear; + private SEntry!T* first; + private SEntry!T* rear; - mixin DefaultAllocator; + mixin DefaultAllocator; } /// unittest { - Queue!int q; + Queue!int q; - q.enqueue(5); - assert(!q.empty); + q.enqueue(5); + assert(!q.empty); - q.enqueue(4); - q.enqueue(9); + q.enqueue(4); + q.enqueue(9); - assert(q.dequeue() == 5); + assert(q.dequeue() == 5); - foreach (i, ref e; q) - { - assert(i != 0 || e == 4); - assert(i != 1 || e == 9); - } - assert(q.empty); + foreach (i, ref e; q) + { + assert(i != 0 || e == 4); + assert(i != 1 || e == 9); + } + assert(q.empty); } diff --git a/source/tanya/container/vector.d b/source/tanya/container/vector.d index c14e060..0f3dc00 100644 --- a/source/tanya/container/vector.d +++ b/source/tanya/container/vector.d @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** - * One-dimensional array. + * Single-dimensioned array. * * Copyright: Eugene Wissner 2016-2017. * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, @@ -166,10 +166,10 @@ struct Vector(T) * range or a static array $(D_PARAM init). * * Params: - * R = Type of the initial range or size of the static array. - * init = Values to initialize the array with. - * to generate a list. - * allocator = Allocator. + * R = Type of the initial range or size of the static array. + * init = Values to initialize the array with. + * to generate a list. + * allocator = Allocator. */ this(size_t R)(T[R] init, shared Allocator allocator = defaultAllocator) { @@ -200,9 +200,9 @@ struct Vector(T) * If $(D_PARAM init) is passed by reference, it will be copied. * * Params: - * R = Vector type. - * init = Source vector. - * allocator = Allocator. + * R = Vector type. + * init = Source vector. + * allocator = Allocator. */ this(R)(ref R init, shared Allocator allocator = defaultAllocator) if (is(Unqual!R == Vector)) @@ -268,8 +268,8 @@ struct Vector(T) * Creates a new $(D_PSYMBOL Vector). * * Params: - * len = Initial length of the vector. - * allocator = Allocator. + * len = Initial length of the vector. + * allocator = Allocator. */ this(in size_t len, shared Allocator allocator = defaultAllocator) { @@ -281,9 +281,9 @@ struct Vector(T) * Creates a new $(D_PSYMBOL Vector). * * Params: - * len = Initial length of the vector. - * init = Initial value to fill the vector with. - * allocator = Allocator. + * len = Initial length of the vector. + * init = Initial value to fill the vector with. + * allocator = Allocator. */ this(in size_t len, T init, shared Allocator allocator = defaultAllocator) @trusted { @@ -399,7 +399,7 @@ struct Vector(T) * Expands/shrinks the vector. * * Params: - * len = New length. + * len = New length. */ @property void length(in size_t len) @trusted { @@ -456,7 +456,7 @@ struct Vector(T) * affected. * * Params: - * size = Desired size. + * size = Desired size. */ void reserve(in size_t size) @trusted { @@ -514,7 +514,7 @@ struct Vector(T) * $(D_PARAM length). * * Params: - * size = Desired size. + * size = Desired size. */ void shrink(in size_t size) @trusted { @@ -585,7 +585,7 @@ struct Vector(T) * length, all elements are removed. * * Params: - * howMany = How many elements should be removed. + * howMany = How many elements should be removed. * * Returns: The number of elements removed */ @@ -618,7 +618,7 @@ struct Vector(T) * Remove all elements beloning to $(D_PARAM r). * * Params: - * r = Range originally obtained from this vector. + * r = Range originally obtained from this vector. * * Returns: Elements in $(D_PARAM r) after removing. * @@ -674,8 +674,8 @@ struct Vector(T) * Inserts the $(D_PARAM el) into the vector. * * Params: - * R = Type of the inserted value(s) (single value, range or static array). - * el = Value(s) should be inserted. + * R = Type of the inserted value(s) (single value, range or static array). + * el = Value(s) should be inserted. * * Returns: The number of elements inserted. */ @@ -767,9 +767,9 @@ struct Vector(T) * Inserts $(D_PARAM el) before or after $(D_PARAM r). * * Params: - * R = Type of the inserted value(s) (single value, range or static array). - * r = Range originally obtained from this vector. - * el = Value(s) should be inserted. + * R = Type of the inserted value(s) (single value, range or static array). + * r = Range originally obtained from this vector. + * el = Value(s) should be inserted. * * Returns: The number of elements inserted. */ @@ -946,8 +946,8 @@ struct Vector(T) * Assigns a value to the element with the index $(D_PARAM pos). * * Params: - * value = Value. - * pos = Position. + * value = Value. + * pos = Position. * * Returns: Assigned value. * @@ -987,8 +987,8 @@ struct Vector(T) * Assigns a range or a static array. * * Params: - * R = Range type or static array length. - * value = Value. + * R = Range type or static array length. + * value = Value. * * Returns: Assigned value. * @@ -1025,7 +1025,7 @@ struct Vector(T) /** * Params: - * pos = Index. + * pos = Index. * * Returns: The value at a specified index. * @@ -1073,7 +1073,7 @@ struct Vector(T) * Comparison for equality. * * Params: - * that = The vector to compare with. + * that = The vector to compare with. * * Returns: $(D_KEYWORD true) if the vectors are equal, $(D_KEYWORD false) * otherwise. @@ -1099,8 +1099,8 @@ struct Vector(T) * Comparison for equality. * * Params: - * R = Right hand side type. - * that = Right hand side vector range. + * R = Right hand side type. + * that = Right hand side vector range. * * Returns: $(D_KEYWORD true) if the vector and the range are equal, * $(D_KEYWORD false) otherwise. @@ -1135,7 +1135,7 @@ struct Vector(T) * $(D_KEYWORD foreach) iteration. * * Params: - * dg = $(D_KEYWORD foreach) body. + * dg = $(D_KEYWORD foreach) body. * * Returns: The value returned from $(D_PARAM dg). */ @@ -1301,8 +1301,8 @@ struct Vector(T) /** * Params: - * i = Slice start. - * j = Slice end. + * i = Slice start. + * j = Slice end. * * Returns: A range that iterates over elements of the container from * index $(D_PARAM i) up to (excluding) index $(D_PARAM j). @@ -1380,11 +1380,11 @@ struct Vector(T) * Slicing assignment. * * Params: - * R = Type of the assigned slice or length of the static array should be - * assigned. - * value = New value (single value, input range or static array). - * i = Slice start. - * j = Slice end. + * R = Type of the assigned slice or length of the static array should be + * assigned. + * value = New value (single value, input range or static array). + * i = Slice start. + * j = Slice end. * * Returns: Slice with the assigned part of the vector. *