summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2017-04-02 11:16:08 +0200
committerEugen Wissner <belka@caraus.de>2017-04-02 11:16:08 +0200
commitb08d5e5d83e506a598e4f1bf8954562661fb5f84 (patch)
tree457b357d377939a235ee33d2fa717f189862db50 /source
parent445b872e91e0256bce27fc9c7f271f728ed5bbee (diff)
downloadtanya-b08d5e5d83e506a598e4f1bf8954562661fb5f84.tar.gz
Add tanya.network.inet.toHostOrder
The function reverts NetworkOrder.
Diffstat (limited to 'source')
-rw-r--r--source/tanya/network/inet.d75
1 files changed, 71 insertions, 4 deletions
diff --git a/source/tanya/network/inet.d b/source/tanya/network/inet.d
index 97da907..75d610c 100644
--- a/source/tanya/network/inet.d
+++ b/source/tanya/network/inet.d
@@ -13,6 +13,7 @@
module tanya.network.inet;
import std.algorithm.comparison;
+import std.range.primitives;
import std.traits;
version (assert)
@@ -23,7 +24,6 @@ version (assert)
version (unittest)
{
import std.math;
- import std.range.primitives;
version (Windows)
{
@@ -74,11 +74,10 @@ struct NetworkOrder
* && value <= 2 ^ (length * 8) - 1).
*/
this(T)(const T value, const size_t length)
- if (isIntegral!T)
+ if (isIntegral!T && isUnsigned!T)
in
{
assert(length <= uint.sizeof);
- assert(value >= 0);
assert(value <= pow(2, length * 8) - 1);
}
body
@@ -89,7 +88,7 @@ struct NetworkOrder
/// Ditto.
this(T)(const T value)
- if (isIntegral!T)
+ if (isIntegral!T && isUnsigned!T)
{
this(value, min(T.sizeof, uint.sizeof));
}
@@ -290,3 +289,71 @@ version (PlattformUnittest)
assert(networkOrder.empty);
}
}
+
+/**
+ * Converts the $(D_KEYWORD ubyte) input range $(D_PARAM r) to
+ * $(D_KEYWORD uint).
+ *
+ * The byte order of $(D_PARAM r) assumed to be big-endian. The length
+ * cannot be larger than $(D_INLINECODE uint.sizeof). Otherwise an assertion
+ * failure will be caused.
+ *
+ * Params:
+ * R = Range type.
+ * range = Input range.
+ *
+ * Returns: $(D_KEYWORD uint) representation of $(D_PARAM range) with host byte
+ * order.
+ */
+uint toHostOrder(R)(R range)
+ if (isInputRange!R && is(Unqual!(ElementType!R) == ubyte) && !isInfinite!R)
+{
+ uint ret;
+ ushort pos = 32;
+
+ for (; !range.empty && range.front == 0; pos -= 8, range.popFront())
+ {
+ }
+ for (; !range.empty; range.popFront())
+ {
+ assert(pos != 0);
+ pos -= 8;
+ ret |= range.front << pos;
+ }
+
+ return ret >> pos;
+}
+
+///
+unittest
+{
+ const value = 0xae34e2u;
+ auto networkOrder = NetworkOrder(value);
+ assert(networkOrder.toHostOrder() == value);
+}
+
+// Tests against the system's htonl, htons.
+version (PlattformUnittest)
+{
+ private unittest
+ {
+ for (uint counter; counter <= 8 * uint.sizeof; ++counter)
+ {
+ const value = pow(2, counter) - 1;
+ const inNetworkOrder = htonl(value);
+ const p = cast(ubyte*) &inNetworkOrder;
+ auto networkOrder = NetworkOrder(value);
+
+ assert(p[0 .. uint.sizeof].toHostOrder() == value);
+ }
+ for (ushort counter; counter <= 8 * ushort.sizeof; ++counter)
+ {
+ const value = cast(ushort) (pow(2, counter) - 1);
+ const inNetworkOrder = htons(value);
+ const p = cast(ubyte*) &inNetworkOrder;
+ auto networkOrder = NetworkOrder(value);
+
+ assert(p[0 .. ushort.sizeof].toHostOrder() == value);
+ }
+ }
+}