summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/tanya/algorithm/iteration.d2
-rw-r--r--source/tanya/algorithm/mutation.d2
-rw-r--r--source/tanya/algorithm/package.d2
-rw-r--r--source/tanya/container/array.d2
-rw-r--r--source/tanya/container/buffer.d1362
-rw-r--r--source/tanya/container/entry.d2
-rw-r--r--source/tanya/container/hashtable.d4
-rw-r--r--source/tanya/container/list.d2
-rw-r--r--source/tanya/container/package.d2
-rw-r--r--source/tanya/container/set.d2
-rw-r--r--source/tanya/container/string.d2
-rw-r--r--source/tanya/conv.d2
-rw-r--r--source/tanya/format.d2
-rw-r--r--source/tanya/hash/lookup.d2
-rw-r--r--source/tanya/hash/package.d2
-rw-r--r--source/tanya/math/package.d2
-rw-r--r--source/tanya/math/random.d2
-rw-r--r--source/tanya/net/iface.d356
-rw-r--r--source/tanya/net/inet.d2
-rw-r--r--source/tanya/net/ip.d2
-rw-r--r--source/tanya/net/package.d2
-rw-r--r--source/tanya/net/uri.d8
-rw-r--r--source/tanya/range/adapter.d2
-rw-r--r--source/tanya/range/array.d2
-rw-r--r--source/tanya/range/package.d2
-rw-r--r--source/tanya/range/primitive.d2
26 files changed, 887 insertions, 887 deletions
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)