diff options
| author | Eugen Wissner <belka@caraus.de> | 2025-08-24 09:01:59 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2025-08-24 09:01:59 +0200 |
| commit | 1857d59375b3fc6d434f7a028143102d0e29ed34 (patch) | |
| tree | f6d8e4e4fc811d9cd3d60d5e5992c035a8e137fc | |
| parent | 6072bfab6818eb038d31491c53bde1092cf1b70d (diff) | |
| download | tanya-1857d59375b3fc6d434f7a028143102d0e29ed34.tar.gz | |
Update copyrights to 2025
43 files changed, 909 insertions, 909 deletions
diff --git a/meta/tanya/meta/metafunction.d b/meta/tanya/meta/metafunction.d index eaa5111..eeb0d56 100644 --- a/meta/tanya/meta/metafunction.d +++ b/meta/tanya/meta/metafunction.d @@ -9,7 +9,7 @@ * It contains different algorithms for iterating, searching and modifying * template arguments. * - * Copyright: Eugene Wissner 2017-2020. + * Copyright: Eugene Wissner 2017-2025. * 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) @@ -34,7 +34,7 @@ import tanya.meta.transform; * $(D_INLINECODE Args[0] < Args[1]), a positive number that * $(D_INLINECODE Args[0] > Args[1]), `0` if they equal.) * ) - * + * * Params: * pred = Template predicate. * Args = Elements for which you want to find the minimum value. @@ -81,7 +81,7 @@ if (Args.length > 0 && __traits(isTemplate, pred)) * $(D_INLINECODE Args[0] < Args[1]), a positive number that * $(D_INLINECODE Args[0] > Args[1]), `0` if they equal.) * ) - * + * * Params: * pred = Template predicate. * Args = Elements for which you want to find the maximum value. @@ -792,7 +792,7 @@ alias AliasSeq(Args...) = Args; * so $(D_INLINECODE F!([0]) && F!([1])) and so on, can be called. * * Params: - * F = Template predicate. + * F = Template predicate. * L = List of items to test. * * Returns: $(D_KEYWORD true) if all the items of $(D_PARAM L) satisfy @@ -815,7 +815,7 @@ enum bool allSatisfy(alias F, L...) = Filter!(templateNot!F, L).length == 0; * so $(D_INLINECODE F!([0]) && F!([1])) and so on, can be called. * * Params: - * F = Template predicate. + * F = Template predicate. * L = List of items to test. * * Returns: $(D_KEYWORD true) if any of the items of $(D_PARAM L) satisfy diff --git a/meta/tanya/meta/package.d b/meta/tanya/meta/package.d index 377626d..d962b12 100644 --- a/meta/tanya/meta/package.d +++ b/meta/tanya/meta/package.d @@ -9,7 +9,7 @@ * to transform from one type to another. It has also different algorithms for * iterating, searching and modifying template arguments. * - * Copyright: Eugene Wissner 2017-2020. + * Copyright: Eugene Wissner 2017-2025. * 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) diff --git a/meta/tanya/meta/trait.d b/meta/tanya/meta/trait.d index 2d81a9e..b91d673 100644 --- a/meta/tanya/meta/trait.d +++ b/meta/tanya/meta/trait.d @@ -8,7 +8,7 @@ * Templates in this module are used to obtain type information at compile * time. * - * Copyright: Eugene Wissner 2017-2020. + * Copyright: Eugene Wissner 2017-2025. * 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) diff --git a/meta/tanya/meta/transform.d b/meta/tanya/meta/transform.d index 08b1b34..2bef67f 100644 --- a/meta/tanya/meta/transform.d +++ b/meta/tanya/meta/transform.d @@ -9,7 +9,7 @@ * types. They take some type as argument and return a different type after * perfoming the specified transformation. * - * Copyright: Eugene Wissner 2017-2020. + * Copyright: Eugene Wissner 2017-2025. * 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) diff --git a/middle/middle-test-library b/middle/middle-test-library Binary files differdeleted file mode 100755 index b8c40ab..0000000 --- a/middle/middle-test-library +++ /dev/null diff --git a/middle/tanya/memory/allocator.d b/middle/tanya/memory/allocator.d index 064ab37..188eff9 100644 --- a/middle/tanya/memory/allocator.d +++ b/middle/tanya/memory/allocator.d @@ -6,9 +6,9 @@ * This module contains the interface for implementing custom allocators. * * Allocators are classes encapsulating memory allocation strategy. This allows - * to decouple memory management from the algorithms and the data. + * to decouple memory management from the algorithms and the data. * - * Copyright: Eugene Wissner 2016-2020. + * Copyright: Eugene Wissner 2016-2025. * 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) diff --git a/middle/tanya/memory/lifetime.d b/middle/tanya/memory/lifetime.d index 8a8cfe9..606086f 100644 --- a/middle/tanya/memory/lifetime.d +++ b/middle/tanya/memory/lifetime.d @@ -5,7 +5,7 @@ /** * Lifetime management functions, types and related exceptions. * - * Copyright: Eugene Wissner 2019-2020. + * Copyright: Eugene Wissner 2019-2025. * 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) diff --git a/middle/tanya/memory/mallocator.d b/middle/tanya/memory/mallocator.d index 69a2876..49eb424 100644 --- a/middle/tanya/memory/mallocator.d +++ b/middle/tanya/memory/mallocator.d @@ -6,7 +6,7 @@ * Allocator based on $(D_PSYMBOL malloc), $(D_PSYMBOL realloc) and * $(D_PSYMBOL free). * - * Copyright: Eugene Wissner 2017-2020. + * Copyright: Eugene Wissner 2017-2025. * 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) diff --git a/middle/tanya/memory/mmappool.d b/middle/tanya/memory/mmappool.d index 3ce49d5..1986c97 100644 --- a/middle/tanya/memory/mmappool.d +++ b/middle/tanya/memory/mmappool.d @@ -5,7 +5,7 @@ /* * Native allocator. * - * Copyright: Eugene Wissner 2016-2020. + * Copyright: Eugene Wissner 2016-2025. * 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) diff --git a/middle/tanya/memory/op.d b/middle/tanya/memory/op.d index a41149b..a266140 100644 --- a/middle/tanya/memory/op.d +++ b/middle/tanya/memory/op.d @@ -1,11 +1,11 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public +/* 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/. */ /** * Set of operations on memory blocks. * - * Copyright: Eugene Wissner 2017-2020. + * Copyright: Eugene Wissner 2017-2025. * 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) diff --git a/middle/tanya/memory/package.d b/middle/tanya/memory/package.d index 61e98d2..e3c20d6 100644 --- a/middle/tanya/memory/package.d +++ b/middle/tanya/memory/package.d @@ -5,7 +5,7 @@ /** * Dynamic memory management. * - * Copyright: Eugene Wissner 2016-2020. + * Copyright: Eugene Wissner 2016-2025. * 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) diff --git a/middle/tanya/memory/smartref.d b/middle/tanya/memory/smartref.d index b6ec374..01a90e1 100644 --- a/middle/tanya/memory/smartref.d +++ b/middle/tanya/memory/smartref.d @@ -14,7 +14,7 @@ * $(LI Unique ownership) * ) * - * Copyright: Eugene Wissner 2016-2020. + * Copyright: Eugene Wissner 2016-2025. * 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) diff --git a/os/tanya/os/error.d b/os/tanya/os/error.d index b271517..3268a8a 100644 --- a/os/tanya/os/error.d +++ b/os/tanya/os/error.d @@ -5,7 +5,7 @@ /** * This module provides a portable way of using operating system error codes. * - * Copyright: Eugene Wissner 2017-2020. + * Copyright: Eugene Wissner 2017-2025. * 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) diff --git a/os/tanya/os/package.d b/os/tanya/os/package.d index 399e975..9b81c18 100644 --- a/os/tanya/os/package.d +++ b/os/tanya/os/package.d @@ -6,7 +6,7 @@ * This package provides platform-independent interfaces to operating system * functionality. * - * Copyright: Eugene Wissner 2017-2020. + * Copyright: Eugene Wissner 2017-2025. * 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) diff --git a/source/tanya/algorithm/iteration.d b/source/tanya/algorithm/iteration.d index 5efc676..469699c 100644 --- a/source/tanya/algorithm/iteration.d +++ b/source/tanya/algorithm/iteration.d @@ -11,7 +11,7 @@ * All algorithms in this module are lazy, they request the next element of the * original range on demand. * - * Copyright: Eugene Wissner 2018-2021. + * Copyright: Eugene Wissner 2018-2025. * 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) diff --git a/source/tanya/algorithm/mutation.d b/source/tanya/algorithm/mutation.d index 6a6edd6..da5ed96 100644 --- a/source/tanya/algorithm/mutation.d +++ b/source/tanya/algorithm/mutation.d @@ -5,7 +5,7 @@ /** * Algorithms that modify its arguments. * - * Copyright: Eugene Wissner 2017-2020. + * Copyright: Eugene Wissner 2017-2025. * 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) diff --git a/source/tanya/algorithm/package.d b/source/tanya/algorithm/package.d index 90e9a8a..b15564d 100644 --- a/source/tanya/algorithm/package.d +++ b/source/tanya/algorithm/package.d @@ -5,7 +5,7 @@ /** * Collection of generic algorithms. * - * Copyright: Eugene Wissner 2017-2021. + * Copyright: Eugene Wissner 2017-2025. * 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) diff --git a/source/tanya/container/array.d b/source/tanya/container/array.d index f5aabcf..7027641 100644 --- a/source/tanya/container/array.d +++ b/source/tanya/container/array.d @@ -5,7 +5,7 @@ /** * Single-dimensioned array. * - * Copyright: Eugene Wissner 2016-2021. + * Copyright: Eugene Wissner 2016-2025. * 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) diff --git a/source/tanya/container/buffer.d b/source/tanya/container/buffer.d index 6c8a1e2..35d83a5 100644 --- a/source/tanya/container/buffer.d +++ b/source/tanya/container/buffer.d @@ -1,681 +1,681 @@ -/* 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/. */
-
-/**
- * This module contains buffers designed for C-style input/output APIs.
- *
- * Copyright: Eugene Wissner 2016-2020.
- * 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)
- * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/container/buffer.d,
- * tanya/container/buffer.d)
- */
-module tanya.container.buffer;
-
-import std.traits : isScalarType;
-import tanya.memory.allocator;
-import tanya.meta.trait;
-
-version (unittest)
-{
- private int fillBuffer(ubyte[] buffer,
- int start = 0,
- int end = 10) @nogc pure nothrow
- in
- {
- assert(start < end);
- }
- do
- {
- auto numberRead = end - start;
- for (ubyte i; i < numberRead; ++i)
- {
- buffer[i] = cast(ubyte) (start + i);
- }
- return numberRead;
- }
-}
-
-/**
- * Self-expanding buffer, that can be used with functions returning the number
- * of the read bytes.
- *
- * This buffer supports asynchronous reading. It means you can pass a new chunk
- * to an asynchronous read function during you are working with already
- * available data. But only one asynchronous call at a time is supported. Be
- * sure to call $(D_PSYMBOL ReadBuffer.clear()) before you append the result
- * of the pended asynchronous call.
- *
- * Params:
- * T = Buffer type.
- */
-struct ReadBuffer(T = ubyte)
-if (isScalarType!T)
-{
- /// Internal buffer.
- private T[] buffer_;
-
- /// Filled buffer length.
- private size_t length_;
-
- /// Start of available data.
- private size_t start;
-
- /// Last position returned with $(D_KEYWORD []).
- private size_t ring;
-
- /// Available space.
- private size_t minAvailable = 1024;
-
- /// Size by which the buffer will grow.
- private size_t blockSize = 8192;
-
- invariant
- {
- assert(this.length_ <= this.buffer_.length);
- assert(this.blockSize > 0);
- assert(this.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(size_t size,
- size_t minAvailable = 1024,
- shared Allocator allocator = defaultAllocator) @trusted
- {
- this(allocator);
- this.minAvailable = minAvailable;
- this.blockSize = size;
- this.buffer_ = cast(T[]) allocator_.allocate(size * T.sizeof);
- }
-
- /// ditto
- this(shared Allocator allocator)
- in
- {
- assert(allocator_ is null);
- }
- do
- {
- allocator_ = allocator;
- }
-
- /**
- * Deallocates the internal buffer.
- */
- ~this() @trusted
- {
- allocator.deallocate(this.buffer_);
- }
-
- ///
- @nogc nothrow pure @safe 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 this.buffer_.length;
- }
-
- /**
- * Returns: Data size.
- */
- @property size_t length() const
- {
- return this.length_ - start;
- }
-
- /// ditto
- alias opDollar = length;
-
- /**
- * Clears the buffer.
- *
- * Returns: $(D_KEYWORD this).
- */
- void clear()
- {
- start = this.length_ = ring;
- }
-
- /**
- * Returns: Available space.
- */
- @property size_t free() const
- {
- return length > ring ? capacity - length : capacity - ring;
- }
-
- ///
- @nogc nothrow pure @system unittest
- {
- ReadBuffer!ubyte b;
- size_t numberRead;
-
- assert(b.free == 0);
-
- // Fills the buffer with values 0..10
- numberRead = fillBuffer(b[], 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)(size_t length)
- if (op == "+")
- {
- this.length_ += length;
- ring = start;
- return this;
- }
-
- ///
- @nogc nothrow pure @system unittest
- {
- ReadBuffer!ubyte b;
- size_t numberRead;
- ubyte[] result;
-
- // Fills the buffer with values 0..10
- numberRead = fillBuffer(b[], 0, 10);
- b += numberRead;
-
- 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[], 0, 10);
- b += numberRead;
-
- numberRead = fillBuffer(b[], 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);
- }
-
- /**
- * Params:
- * start = Start position.
- * end = End position.
- *
- * Returns: Array between $(D_PARAM start) and $(D_PARAM end).
- */
- T[] opSlice(size_t start, size_t end)
- {
- return this.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 = this.buffer_[0 .. start];
- ring = 0;
- return ret;
- }
- else
- {
- if (capacity - length < this.minAvailable)
- {
- void[] buf = this.buffer_;
- const cap = capacity;
- () @trusted {
- allocator.reallocate(buf,
- (cap + this.blockSize) * T.sizeof);
- this.buffer_ = cast(T[]) buf;
- }();
- }
- ring = this.length_;
- return this.buffer_[this.length_ .. $];
- }
- }
-
- ///
- @nogc nothrow pure @system unittest
- {
- ReadBuffer!ubyte b;
- size_t numberRead;
- ubyte[] result;
-
- // Fills the buffer with values 0..10
- numberRead = fillBuffer(b[], 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);
- }
-
- mixin DefaultAllocator;
-}
-
-/**
- * Circular, self-expanding buffer with overflow support. Can be used with
- * functions returning the number of the transferred bytes.
- *
- * The buffer is optimized for situations where you read all the data from it
- * at once (without writing to it occasionally). It can become ineffective if
- * you permanently keep some data in the buffer and alternate writing and
- * reading, because it may allocate and move elements.
- *
- * Params:
- * T = Buffer type.
- */
-struct WriteBuffer(T = ubyte)
-if (isScalarType!T)
-{
- /// Internal buffer.
- private T[] buffer_;
-
- /// Buffer start position.
- private size_t start;
-
- /// Buffer ring area size. After this position begins buffer overflow area.
- private size_t ring;
-
- /// Size by which the buffer will grow.
- private const size_t blockSize;
-
- /// The position of the free area in the buffer.
- private size_t position;
-
- invariant
- {
- assert(this.blockSize > 0);
- // Position can refer to an element outside the buffer if the buffer is
- // full.
- assert(this.position <= this.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(size_t size, shared Allocator allocator = defaultAllocator) @trusted
- in
- {
- assert(size > 0);
- assert(allocator !is null);
- }
- do
- {
- this.blockSize = size;
- ring = size - 1;
- allocator_ = allocator;
- this.buffer_ = cast(T[]) allocator_.allocate(size * T.sizeof);
- }
-
- @disable this();
-
- /**
- * Deallocates the internal buffer.
- */
- ~this()
- {
- allocator.deallocate(this.buffer_);
- }
-
- /**
- * Returns: The size of the internal buffer.
- */
- @property size_t capacity() const
- {
- return this.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 (this.position > ring || this.position < start) // Buffer overflowed
- {
- return ring - start + 1;
- }
- else
- {
- return this.position - start;
- }
- }
-
- /// ditto
- alias opDollar = length;
-
- ///
- @nogc nothrow pure @system 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 == 2);
- b += 2;
- assert(b.length == 2);
-
- b ~= buf;
- assert(b.length == 5);
- b += b.length;
- assert(b.length == 0);
- }
-
- /**
- * 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)(const T[] buffer)
- if (op == "~")
- {
- size_t end, start;
-
- if (this.position >= this.start && this.position <= ring)
- {
- auto afterRing = ring + 1;
-
- end = this.position + buffer.length;
- if (end > afterRing)
- {
- end = afterRing;
- }
- start = end - this.position;
- this.buffer_[this.position .. end] = buffer[0 .. start];
- if (end == afterRing)
- {
- this.position = this.start == 0 ? afterRing : 0;
- }
- else
- {
- this.position = end;
- }
- }
-
- // Check if we have some free space at the beginning
- if (start < buffer.length && this.position < this.start)
- {
- end = this.position + buffer.length - start;
- if (end > this.start)
- {
- end = this.start;
- }
- auto areaEnd = end - this.position + start;
- this.buffer_[this.position .. end] = buffer[start .. areaEnd];
- this.position = end == this.start ? ring + 1 : end - this.position;
- start = areaEnd;
- }
-
- // And if we still haven't found any place, save the rest in the overflow area
- if (start < buffer.length)
- {
- end = this.position + buffer.length - start;
- if (end > capacity)
- {
- const newSize = end / this.blockSize * this.blockSize
- + this.blockSize;
- () @trusted {
- void[] buf = this.buffer_;
- allocator.reallocate(buf, newSize * T.sizeof);
- this.buffer_ = cast(T[]) buf;
- }();
- }
- this.buffer_[this.position .. end] = buffer[start .. $];
- this.position = end;
- if (this.start == 0)
- {
- ring = capacity - 1;
- }
- }
-
- return this;
- }
-
- /**
- * 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)(size_t length)
- if (op == "+")
- in
- {
- assert(length <= this.length);
- }
- do
- {
- auto afterRing = ring + 1;
- auto oldStart = start;
-
- if (length <= 0)
- {
- return this;
- }
- else if (this.position <= afterRing)
- {
- start += length;
- if (start > 0 && this.position == afterRing)
- {
- this.position = oldStart;
- }
- }
- else
- {
- auto overflow = this.position - afterRing;
-
- if (overflow > length)
- {
- const afterLength = afterRing + length;
- this.buffer_[start .. start + length] = this.buffer_[afterRing .. afterLength];
- this.buffer_[afterRing .. afterLength] = this.buffer_[afterLength .. this.position];
- this.position -= length;
- }
- else if (overflow == length)
- {
- this.buffer_[start .. start + overflow] = this.buffer_[afterRing .. this.position];
- this.position -= overflow;
- }
- else
- {
- this.buffer_[start .. start + overflow] = this.buffer_[afterRing .. this.position];
- this.position = overflow;
- }
- start += length;
-
- if (start == this.position)
- {
- if (this.position != afterRing)
- {
- this.position = 0;
- }
- start = 0;
- ring = capacity - 1;
- }
- }
- if (start > ring)
- {
- start = 0;
- }
- return this;
- }
-
- ///
- @nogc nothrow pure @system 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);
- }
-
- /**
- * 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(size_t start, size_t end)
- {
- if (this.position > ring || this.position < start) // Buffer overflowed
- {
- return this.buffer_[this.start .. ring + 1 - length + end];
- }
- else
- {
- return this.buffer_[this.start .. this.start + end];
- }
- }
-
- ///
- @nogc nothrow pure @system 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;
-
- assert(b[0 .. $] == buf[2 .. 6]);
-
- b ~= buf;
- assert(b[0 .. $] == buf[2 .. 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);
- }
-
- mixin DefaultAllocator;
-}
-
-@nogc nothrow pure @system 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 += 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);
-}
-
-@nogc nothrow pure @system 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);
-}
+/* 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/. */ + +/** + * This module contains buffers designed for C-style input/output APIs. + * + * Copyright: Eugene Wissner 2016-2025. + * 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) + * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/container/buffer.d, + * tanya/container/buffer.d) + */ +module tanya.container.buffer; + +import std.traits : isScalarType; +import tanya.memory.allocator; +import tanya.meta.trait; + +version (unittest) +{ + private int fillBuffer(ubyte[] buffer, + int start = 0, + int end = 10) @nogc pure nothrow + in + { + assert(start < end); + } + do + { + auto numberRead = end - start; + for (ubyte i; i < numberRead; ++i) + { + buffer[i] = cast(ubyte) (start + i); + } + return numberRead; + } +} + +/** + * Self-expanding buffer, that can be used with functions returning the number + * of the read bytes. + * + * This buffer supports asynchronous reading. It means you can pass a new chunk + * to an asynchronous read function during you are working with already + * available data. But only one asynchronous call at a time is supported. Be + * sure to call $(D_PSYMBOL ReadBuffer.clear()) before you append the result + * of the pended asynchronous call. + * + * Params: + * T = Buffer type. + */ +struct ReadBuffer(T = ubyte) +if (isScalarType!T) +{ + /// Internal buffer. + private T[] buffer_; + + /// Filled buffer length. + private size_t length_; + + /// Start of available data. + private size_t start; + + /// Last position returned with $(D_KEYWORD []). + private size_t ring; + + /// Available space. + private size_t minAvailable = 1024; + + /// Size by which the buffer will grow. + private size_t blockSize = 8192; + + invariant + { + assert(this.length_ <= this.buffer_.length); + assert(this.blockSize > 0); + assert(this.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(size_t size, + size_t minAvailable = 1024, + shared Allocator allocator = defaultAllocator) @trusted + { + this(allocator); + this.minAvailable = minAvailable; + this.blockSize = size; + this.buffer_ = cast(T[]) allocator_.allocate(size * T.sizeof); + } + + /// ditto + this(shared Allocator allocator) + in + { + assert(allocator_ is null); + } + do + { + allocator_ = allocator; + } + + /** + * Deallocates the internal buffer. + */ + ~this() @trusted + { + allocator.deallocate(this.buffer_); + } + + /// + @nogc nothrow pure @safe 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 this.buffer_.length; + } + + /** + * Returns: Data size. + */ + @property size_t length() const + { + return this.length_ - start; + } + + /// ditto + alias opDollar = length; + + /** + * Clears the buffer. + * + * Returns: $(D_KEYWORD this). + */ + void clear() + { + start = this.length_ = ring; + } + + /** + * Returns: Available space. + */ + @property size_t free() const + { + return length > ring ? capacity - length : capacity - ring; + } + + /// + @nogc nothrow pure @system unittest + { + ReadBuffer!ubyte b; + size_t numberRead; + + assert(b.free == 0); + + // Fills the buffer with values 0..10 + numberRead = fillBuffer(b[], 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)(size_t length) + if (op == "+") + { + this.length_ += length; + ring = start; + return this; + } + + /// + @nogc nothrow pure @system unittest + { + ReadBuffer!ubyte b; + size_t numberRead; + ubyte[] result; + + // Fills the buffer with values 0..10 + numberRead = fillBuffer(b[], 0, 10); + b += numberRead; + + 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[], 0, 10); + b += numberRead; + + numberRead = fillBuffer(b[], 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); + } + + /** + * Params: + * start = Start position. + * end = End position. + * + * Returns: Array between $(D_PARAM start) and $(D_PARAM end). + */ + T[] opSlice(size_t start, size_t end) + { + return this.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 = this.buffer_[0 .. start]; + ring = 0; + return ret; + } + else + { + if (capacity - length < this.minAvailable) + { + void[] buf = this.buffer_; + const cap = capacity; + () @trusted { + allocator.reallocate(buf, + (cap + this.blockSize) * T.sizeof); + this.buffer_ = cast(T[]) buf; + }(); + } + ring = this.length_; + return this.buffer_[this.length_ .. $]; + } + } + + /// + @nogc nothrow pure @system unittest + { + ReadBuffer!ubyte b; + size_t numberRead; + ubyte[] result; + + // Fills the buffer with values 0..10 + numberRead = fillBuffer(b[], 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); + } + + mixin DefaultAllocator; +} + +/** + * Circular, self-expanding buffer with overflow support. Can be used with + * functions returning the number of the transferred bytes. + * + * The buffer is optimized for situations where you read all the data from it + * at once (without writing to it occasionally). It can become ineffective if + * you permanently keep some data in the buffer and alternate writing and + * reading, because it may allocate and move elements. + * + * Params: + * T = Buffer type. + */ +struct WriteBuffer(T = ubyte) +if (isScalarType!T) +{ + /// Internal buffer. + private T[] buffer_; + + /// Buffer start position. + private size_t start; + + /// Buffer ring area size. After this position begins buffer overflow area. + private size_t ring; + + /// Size by which the buffer will grow. + private const size_t blockSize; + + /// The position of the free area in the buffer. + private size_t position; + + invariant + { + assert(this.blockSize > 0); + // Position can refer to an element outside the buffer if the buffer is + // full. + assert(this.position <= this.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(size_t size, shared Allocator allocator = defaultAllocator) @trusted + in + { + assert(size > 0); + assert(allocator !is null); + } + do + { + this.blockSize = size; + ring = size - 1; + allocator_ = allocator; + this.buffer_ = cast(T[]) allocator_.allocate(size * T.sizeof); + } + + @disable this(); + + /** + * Deallocates the internal buffer. + */ + ~this() + { + allocator.deallocate(this.buffer_); + } + + /** + * Returns: The size of the internal buffer. + */ + @property size_t capacity() const + { + return this.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 (this.position > ring || this.position < start) // Buffer overflowed + { + return ring - start + 1; + } + else + { + return this.position - start; + } + } + + /// ditto + alias opDollar = length; + + /// + @nogc nothrow pure @system 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 == 2); + b += 2; + assert(b.length == 2); + + b ~= buf; + assert(b.length == 5); + b += b.length; + assert(b.length == 0); + } + + /** + * 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)(const T[] buffer) + if (op == "~") + { + size_t end, start; + + if (this.position >= this.start && this.position <= ring) + { + auto afterRing = ring + 1; + + end = this.position + buffer.length; + if (end > afterRing) + { + end = afterRing; + } + start = end - this.position; + this.buffer_[this.position .. end] = buffer[0 .. start]; + if (end == afterRing) + { + this.position = this.start == 0 ? afterRing : 0; + } + else + { + this.position = end; + } + } + + // Check if we have some free space at the beginning + if (start < buffer.length && this.position < this.start) + { + end = this.position + buffer.length - start; + if (end > this.start) + { + end = this.start; + } + auto areaEnd = end - this.position + start; + this.buffer_[this.position .. end] = buffer[start .. areaEnd]; + this.position = end == this.start ? ring + 1 : end - this.position; + start = areaEnd; + } + + // And if we still haven't found any place, save the rest in the overflow area + if (start < buffer.length) + { + end = this.position + buffer.length - start; + if (end > capacity) + { + const newSize = end / this.blockSize * this.blockSize + + this.blockSize; + () @trusted { + void[] buf = this.buffer_; + allocator.reallocate(buf, newSize * T.sizeof); + this.buffer_ = cast(T[]) buf; + }(); + } + this.buffer_[this.position .. end] = buffer[start .. $]; + this.position = end; + if (this.start == 0) + { + ring = capacity - 1; + } + } + + return this; + } + + /** + * 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)(size_t length) + if (op == "+") + in + { + assert(length <= this.length); + } + do + { + auto afterRing = ring + 1; + auto oldStart = start; + + if (length <= 0) + { + return this; + } + else if (this.position <= afterRing) + { + start += length; + if (start > 0 && this.position == afterRing) + { + this.position = oldStart; + } + } + else + { + auto overflow = this.position - afterRing; + + if (overflow > length) + { + const afterLength = afterRing + length; + this.buffer_[start .. start + length] = this.buffer_[afterRing .. afterLength]; + this.buffer_[afterRing .. afterLength] = this.buffer_[afterLength .. this.position]; + this.position -= length; + } + else if (overflow == length) + { + this.buffer_[start .. start + overflow] = this.buffer_[afterRing .. this.position]; + this.position -= overflow; + } + else + { + this.buffer_[start .. start + overflow] = this.buffer_[afterRing .. this.position]; + this.position = overflow; + } + start += length; + + if (start == this.position) + { + if (this.position != afterRing) + { + this.position = 0; + } + start = 0; + ring = capacity - 1; + } + } + if (start > ring) + { + start = 0; + } + return this; + } + + /// + @nogc nothrow pure @system 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); + } + + /** + * 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(size_t start, size_t end) + { + if (this.position > ring || this.position < start) // Buffer overflowed + { + return this.buffer_[this.start .. ring + 1 - length + end]; + } + else + { + return this.buffer_[this.start .. this.start + end]; + } + } + + /// + @nogc nothrow pure @system 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; + + assert(b[0 .. $] == buf[2 .. 6]); + + b ~= buf; + assert(b[0 .. $] == buf[2 .. 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); + } + + mixin DefaultAllocator; +} + +@nogc nothrow pure @system 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 += 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); +} + +@nogc nothrow pure @system 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); +} diff --git a/source/tanya/container/entry.d b/source/tanya/container/entry.d index 7ea5ff6..f8414e0 100644 --- a/source/tanya/container/entry.d +++ b/source/tanya/container/entry.d @@ -5,7 +5,7 @@ /* * Internal package used by containers that rely on entries/nodes. * - * Copyright: Eugene Wissner 2016-2022. + * Copyright: Eugene Wissner 2016-2025. * 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) diff --git a/source/tanya/container/hashtable.d b/source/tanya/container/hashtable.d index 723855e..119cc3c 100644 --- a/source/tanya/container/hashtable.d +++ b/source/tanya/container/hashtable.d @@ -5,7 +5,7 @@ /** * Hash table. * - * Copyright: Eugene Wissner 2018-2021. + * Copyright: Eugene Wissner 2018-2025. * 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) @@ -210,7 +210,7 @@ struct ByKey(T) assert(!empty); assert(this.dataRange.back.status == BucketStatus.used); } - out + out { assert(empty || this.dataRange.back.status == BucketStatus.used); } diff --git a/source/tanya/container/list.d b/source/tanya/container/list.d index 90a834b..0c924ec 100644 --- a/source/tanya/container/list.d +++ b/source/tanya/container/list.d @@ -6,7 +6,7 @@ * This module contains singly-linked ($(D_PSYMBOL SList)) and doubly-linked * ($(D_PSYMBOL DList)) lists. * - * Copyright: Eugene Wissner 2016-2021. + * Copyright: Eugene Wissner 2016-2025. * 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) diff --git a/source/tanya/container/package.d b/source/tanya/container/package.d index 5edd72e..ae308d0 100644 --- a/source/tanya/container/package.d +++ b/source/tanya/container/package.d @@ -5,7 +5,7 @@ /** * Abstract data types whose instances are collections of other objects. * - * Copyright: Eugene Wissner 2016-2020. + * Copyright: Eugene Wissner 2016-2025. * 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) diff --git a/source/tanya/container/set.d b/source/tanya/container/set.d index ea95bc8..1b7c1db 100644 --- a/source/tanya/container/set.d +++ b/source/tanya/container/set.d @@ -6,7 +6,7 @@ * This module implements a $(D_PSYMBOL Set) container that stores unique * values without any particular order. * - * Copyright: Eugene Wissner 2017-2020. + * Copyright: Eugene Wissner 2017-2025. * 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) diff --git a/source/tanya/container/string.d b/source/tanya/container/string.d index 88c82d2..a2cd2f2 100644 --- a/source/tanya/container/string.d +++ b/source/tanya/container/string.d @@ -17,7 +17,7 @@ * Internally $(D_PSYMBOL String) is represented by a sequence of * $(D_KEYWORD char)s. * - * Copyright: Eugene Wissner 2017-2020. + * Copyright: Eugene Wissner 2017-2025. * 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) diff --git a/source/tanya/conv.d b/source/tanya/conv.d index 6d6dfdd..7d5a264 100644 --- a/source/tanya/conv.d +++ b/source/tanya/conv.d @@ -5,7 +5,7 @@ /** * This module provides functions for converting between different types. * - * Copyright: Eugene Wissner 2017-2020. + * Copyright: Eugene Wissner 2017-2025. * 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) diff --git a/source/tanya/format.d b/source/tanya/format.d index 8f43cf6..ebe3354 100644 --- a/source/tanya/format.d +++ b/source/tanya/format.d @@ -38,7 +38,7 @@ * * More advanced formatting is currently not implemented. * - * Copyright: Eugene Wissner 2017-2022. + * Copyright: Eugene Wissner 2017-2025. * 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) diff --git a/source/tanya/hash/lookup.d b/source/tanya/hash/lookup.d index 536904d..62faf89 100644 --- a/source/tanya/hash/lookup.d +++ b/source/tanya/hash/lookup.d @@ -5,7 +5,7 @@ /** * Non-cryptographic, lookup hash functions. * - * Copyright: Eugene Wissner 2018-2020. + * Copyright: Eugene Wissner 2018-2025. * 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) diff --git a/source/tanya/hash/package.d b/source/tanya/hash/package.d index b109f48..89f6440 100644 --- a/source/tanya/hash/package.d +++ b/source/tanya/hash/package.d @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** - * Copyright: Eugene Wissner 2018-2020. + * Copyright: Eugene Wissner 2018-2025. * 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) diff --git a/source/tanya/math/package.d b/source/tanya/math/package.d index c632bba..0d10238 100644 --- a/source/tanya/math/package.d +++ b/source/tanya/math/package.d @@ -12,7 +12,7 @@ * be found in its submodules. $(D_PSYMBOL tanya.math) doesn't import any * submodules publically, they should be imported explicitly. * - * Copyright: Eugene Wissner 2016-2022. + * Copyright: Eugene Wissner 2016-2025. * 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) diff --git a/source/tanya/math/random.d b/source/tanya/math/random.d index 646dd59..6146788 100644 --- a/source/tanya/math/random.d +++ b/source/tanya/math/random.d @@ -5,7 +5,7 @@ /** * Random number generator. * - * Copyright: Eugene Wissner 2016-2022. + * Copyright: Eugene Wissner 2016-2025. * 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) diff --git a/source/tanya/net/iface.d b/source/tanya/net/iface.d index 3bc165a..699d09d 100644 --- a/source/tanya/net/iface.d +++ b/source/tanya/net/iface.d @@ -1,178 +1,178 @@ -/* 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/. */
-
-/**
- * Network interfaces.
- *
- * Copyright: Eugene Wissner 2018-2020.
- * 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)
- * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/net/iface.d,
- * tanya/net/iface.d)
- */
-module tanya.net.iface;
-
-import tanya.algorithm.mutation;
-import tanya.container.string;
-import tanya.meta.trait;
-import tanya.meta.transform;
-import tanya.range;
-
-version (Windows)
-{
- private union NET_LUID_LH { ulong Value, Info; }
- private alias NET_LUID = NET_LUID_LH;
- private alias NET_IFINDEX = uint;
- private enum IF_MAX_STRING_SIZE = 256;
- extern(Windows) @nogc nothrow private @system
- {
- uint ConvertInterfaceNameToLuidA(const(char)* InterfaceName,
- NET_LUID* InterfaceLuid);
- uint ConvertInterfaceLuidToIndex(const(NET_LUID)* InterfaceLuid,
- NET_IFINDEX* InterfaceIndex);
- uint ConvertInterfaceIndexToLuid(NET_IFINDEX InterfaceIndex,
- NET_LUID* InterfaceLuid);
- uint ConvertInterfaceLuidToNameA(const(NET_LUID)* InterfaceLuid,
- char* InterfaceName,
- size_t Length);
- }
-}
-else version (Posix)
-{
- import core.sys.posix.net.if_;
-}
-
-/**
- * Converts the name of a network interface to its index.
- *
- * If an interface with the name $(D_PARAM name) cannot be found or another
- * error occurres, returns 0.
- *
- * Params:
- * name = Interface name.
- *
- * Returns: Returns interface index or 0.
- */
-uint nameToIndex(R)(R name) @trusted
-if (isInputRange!R && is(Unqual!(ElementType!R) == char) && hasLength!R)
-{
- version (Windows)
- {
- if (name.length > IF_MAX_STRING_SIZE)
- {
- return 0;
- }
- char[IF_MAX_STRING_SIZE + 1] buffer;
- NET_LUID luid;
-
- copy(name, buffer[]);
- buffer[name.length] = '\0';
-
- if (ConvertInterfaceNameToLuidA(buffer.ptr, &luid) != 0)
- {
- return 0;
- }
- NET_IFINDEX index;
- if (ConvertInterfaceLuidToIndex(&luid, &index) == 0)
- {
- return index;
- }
- return 0;
- }
- else version (Posix)
- {
- if (name.length >= IF_NAMESIZE)
- {
- return 0;
- }
- char[IF_NAMESIZE] buffer;
-
- copy(name, buffer[]);
- buffer[name.length] = '\0';
-
- return if_nametoindex(buffer.ptr);
- }
-}
-
-///
-@nogc nothrow @safe unittest
-{
- version (linux)
- {
- assert(nameToIndex("lo") == 1);
- }
- else version (Windows)
- {
- assert(nameToIndex("loopback_0") == 1);
- }
- else
- {
- assert(nameToIndex("lo0") == 1);
- }
- assert(nameToIndex("ecafretni") == 0);
-}
-
-/**
- * Converts the index of a network interface to its name.
- *
- * If an interface with the $(D_PARAM index) cannot be found or another
- * error occurres, returns an empty $(D_PSYMBOL String).
- *
- * Params:
- * index = Interface index.
- *
- * Returns: Returns interface name or an empty $(D_PSYMBOL String).
- */
-String indexToName(uint index) @nogc nothrow @trusted
-{
- import tanya.memory.op : findNullTerminated;
-
- version (Windows)
- {
- NET_LUID luid;
- if (ConvertInterfaceIndexToLuid(index, &luid) != 0)
- {
- return String();
- }
-
- char[IF_MAX_STRING_SIZE + 1] buffer;
- if (ConvertInterfaceLuidToNameA(&luid,
- buffer.ptr,
- IF_MAX_STRING_SIZE + 1) != 0)
- {
- return String();
- }
- return String(findNullTerminated(buffer));
- }
- else version (Posix)
- {
- char[IF_NAMESIZE] buffer;
- if (if_indextoname(index, buffer.ptr) is null)
- {
- return String();
- }
- return String(findNullTerminated(buffer));
- }
-}
-
-/**
- * $(D_PSYMBOL AddressFamily) specifies a communication domain; this selects
- * the protocol family which will be used for communication.
- */
-enum AddressFamily : int
-{
- unspec = 0, /// Unspecified.
- local = 1, /// Local to host (pipes and file-domain).
- unix = local, /// POSIX name for PF_LOCAL.
- inet = 2, /// IP protocol family.
- ax25 = 3, /// Amateur Radio AX.25.
- ipx = 4, /// Novell Internet Protocol.
- appletalk = 5, /// Appletalk DDP.
- netrom = 6, /// Amateur radio NetROM.
- bridge = 7, /// Multiprotocol bridge.
- atmpvc = 8, /// ATM PVCs.
- x25 = 9, /// Reserved for X.25 project.
- inet6 = 10, /// IP version 6.
-}
+/* 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/. */ + +/** + * Network interfaces. + * + * Copyright: Eugene Wissner 2018-2025. + * 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) + * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/net/iface.d, + * tanya/net/iface.d) + */ +module tanya.net.iface; + +import tanya.algorithm.mutation; +import tanya.container.string; +import tanya.meta.trait; +import tanya.meta.transform; +import tanya.range; + +version (Windows) +{ + private union NET_LUID_LH { ulong Value, Info; } + private alias NET_LUID = NET_LUID_LH; + private alias NET_IFINDEX = uint; + private enum IF_MAX_STRING_SIZE = 256; + extern(Windows) @nogc nothrow private @system + { + uint ConvertInterfaceNameToLuidA(const(char)* InterfaceName, + NET_LUID* InterfaceLuid); + uint ConvertInterfaceLuidToIndex(const(NET_LUID)* InterfaceLuid, + NET_IFINDEX* InterfaceIndex); + uint ConvertInterfaceIndexToLuid(NET_IFINDEX InterfaceIndex, + NET_LUID* InterfaceLuid); + uint ConvertInterfaceLuidToNameA(const(NET_LUID)* InterfaceLuid, + char* InterfaceName, + size_t Length); + } +} +else version (Posix) +{ + import core.sys.posix.net.if_; +} + +/** + * Converts the name of a network interface to its index. + * + * If an interface with the name $(D_PARAM name) cannot be found or another + * error occurres, returns 0. + * + * Params: + * name = Interface name. + * + * Returns: Returns interface index or 0. + */ +uint nameToIndex(R)(R name) @trusted +if (isInputRange!R && is(Unqual!(ElementType!R) == char) && hasLength!R) +{ + version (Windows) + { + if (name.length > IF_MAX_STRING_SIZE) + { + return 0; + } + char[IF_MAX_STRING_SIZE + 1] buffer; + NET_LUID luid; + + copy(name, buffer[]); + buffer[name.length] = '\0'; + + if (ConvertInterfaceNameToLuidA(buffer.ptr, &luid) != 0) + { + return 0; + } + NET_IFINDEX index; + if (ConvertInterfaceLuidToIndex(&luid, &index) == 0) + { + return index; + } + return 0; + } + else version (Posix) + { + if (name.length >= IF_NAMESIZE) + { + return 0; + } + char[IF_NAMESIZE] buffer; + + copy(name, buffer[]); + buffer[name.length] = '\0'; + + return if_nametoindex(buffer.ptr); + } +} + +/// +@nogc nothrow @safe unittest +{ + version (linux) + { + assert(nameToIndex("lo") == 1); + } + else version (Windows) + { + assert(nameToIndex("loopback_0") == 1); + } + else + { + assert(nameToIndex("lo0") == 1); + } + assert(nameToIndex("ecafretni") == 0); +} + +/** + * Converts the index of a network interface to its name. + * + * If an interface with the $(D_PARAM index) cannot be found or another + * error occurres, returns an empty $(D_PSYMBOL String). + * + * Params: + * index = Interface index. + * + * Returns: Returns interface name or an empty $(D_PSYMBOL String). + */ +String indexToName(uint index) @nogc nothrow @trusted +{ + import tanya.memory.op : findNullTerminated; + + version (Windows) + { + NET_LUID luid; + if (ConvertInterfaceIndexToLuid(index, &luid) != 0) + { + return String(); + } + + char[IF_MAX_STRING_SIZE + 1] buffer; + if (ConvertInterfaceLuidToNameA(&luid, + buffer.ptr, + IF_MAX_STRING_SIZE + 1) != 0) + { + return String(); + } + return String(findNullTerminated(buffer)); + } + else version (Posix) + { + char[IF_NAMESIZE] buffer; + if (if_indextoname(index, buffer.ptr) is null) + { + return String(); + } + return String(findNullTerminated(buffer)); + } +} + +/** + * $(D_PSYMBOL AddressFamily) specifies a communication domain; this selects + * the protocol family which will be used for communication. + */ +enum AddressFamily : int +{ + unspec = 0, /// Unspecified. + local = 1, /// Local to host (pipes and file-domain). + unix = local, /// POSIX name for PF_LOCAL. + inet = 2, /// IP protocol family. + ax25 = 3, /// Amateur Radio AX.25. + ipx = 4, /// Novell Internet Protocol. + appletalk = 5, /// Appletalk DDP. + netrom = 6, /// Amateur radio NetROM. + bridge = 7, /// Multiprotocol bridge. + atmpvc = 8, /// ATM PVCs. + x25 = 9, /// Reserved for X.25 project. + inet6 = 10, /// IP version 6. +} diff --git a/source/tanya/net/inet.d b/source/tanya/net/inet.d index 65146b6..7199a3c 100644 --- a/source/tanya/net/inet.d +++ b/source/tanya/net/inet.d @@ -5,7 +5,7 @@ /** * Internet utilities. * - * Copyright: Eugene Wissner 2016-2020. + * Copyright: Eugene Wissner 2016-2025. * 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) diff --git a/source/tanya/net/ip.d b/source/tanya/net/ip.d index 73e7f84..4b6d2f7 100644 --- a/source/tanya/net/ip.d +++ b/source/tanya/net/ip.d @@ -5,7 +5,7 @@ /** * Internet Protocol implementation. * - * Copyright: Eugene Wissner 2018-2020. + * Copyright: Eugene Wissner 2018-2025. * 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) diff --git a/source/tanya/net/package.d b/source/tanya/net/package.d index 9626b9e..f8762a7 100644 --- a/source/tanya/net/package.d +++ b/source/tanya/net/package.d @@ -5,7 +5,7 @@ /** * Network programming. * - * Copyright: Eugene Wissner 2017-2022. + * Copyright: Eugene Wissner 2017-2025. * 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) diff --git a/source/tanya/net/uri.d b/source/tanya/net/uri.d index 419b486..d164724 100644 --- a/source/tanya/net/uri.d +++ b/source/tanya/net/uri.d @@ -5,7 +5,7 @@ /** * URL parser. * - * Copyright: Eugene Wissner 2017-2020. + * Copyright: Eugene Wissner 2017-2025. * 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) @@ -193,7 +193,7 @@ struct URL if (this.user is null) { this.user = source[start .. start + i]; - this.pass = source[start + i + 1 .. pos]; + this.pass = source[start + i + 1 .. pos]; } } else if (!c.isAlpha() && @@ -315,10 +315,10 @@ struct URL @nogc pure @system unittest { auto u = URL("example.org"); - assert(u.path == "example.org"); + assert(u.path == "example.org"); u = URL("relative/path"); - assert(u.path == "relative/path"); + assert(u.path == "relative/path"); // Host and scheme u = URL("https://example.org"); diff --git a/source/tanya/range/adapter.d b/source/tanya/range/adapter.d index 60d4c67..9dfe2f2 100644 --- a/source/tanya/range/adapter.d +++ b/source/tanya/range/adapter.d @@ -5,7 +5,7 @@ /** * Range adapters transform some data structures into ranges. * - * Copyright: Eugene Wissner 2018-2020. + * Copyright: Eugene Wissner 2018-2025. * 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) diff --git a/source/tanya/range/array.d b/source/tanya/range/array.d index bd47fb9..fb0895d 100644 --- a/source/tanya/range/array.d +++ b/source/tanya/range/array.d @@ -31,7 +31,7 @@ * (D_INLINECODE dchar[])) are treated as any other normal array, they aren't * auto-decoded. * - * Copyright: Eugene Wissner 2017-2020. + * Copyright: Eugene Wissner 2017-2025. * 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) diff --git a/source/tanya/range/package.d b/source/tanya/range/package.d index 16ffe8c..e2debfc 100644 --- a/source/tanya/range/package.d +++ b/source/tanya/range/package.d @@ -6,7 +6,7 @@ * This package contains generic functions and templates to be used with D * ranges. * - * Copyright: Eugene Wissner 2017-2020. + * Copyright: Eugene Wissner 2017-2025. * 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) diff --git a/source/tanya/range/primitive.d b/source/tanya/range/primitive.d index 54646a6..3cc45e0 100644 --- a/source/tanya/range/primitive.d +++ b/source/tanya/range/primitive.d @@ -5,7 +5,7 @@ /** * This module defines primitives for working with ranges. * - * Copyright: Eugene Wissner 2017-2020. + * Copyright: Eugene Wissner 2017-2025. * 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) diff --git a/test/tanya/test/assertion.d b/test/tanya/test/assertion.d index ae24fad..5fd9831 100644 --- a/test/tanya/test/assertion.d +++ b/test/tanya/test/assertion.d @@ -13,7 +13,7 @@ * The functions can cause segmentation fault if the module is compiled * in production mode and the condition fails. * - * Copyright: Eugene Wissner 2017-2020. + * Copyright: Eugene Wissner 2017-2025. * 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) diff --git a/test/tanya/test/package.d b/test/tanya/test/package.d index a444a88..f316ddf 100644 --- a/test/tanya/test/package.d +++ b/test/tanya/test/package.d @@ -5,7 +5,7 @@ /** * Test suite for $(D_KEYWORD unittest)-blocks. * - * Copyright: Eugene Wissner 2017-2020. + * Copyright: Eugene Wissner 2017-2025. * 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) diff --git a/test/tanya/test/stub.d b/test/tanya/test/stub.d index 99630e6..a83cf01 100644 --- a/test/tanya/test/stub.d +++ b/test/tanya/test/stub.d @@ -5,7 +5,7 @@ /** * Range and generic type generators. * - * Copyright: Eugene Wissner 2018-2020. + * Copyright: Eugene Wissner 2018-2025. * 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) |
