1 module tagion.utils.Miscellaneous; 2 3 import std.algorithm; 4 import std.array; 5 import std.range; 6 import std.exception; 7 import std.range.primitives : isInputRange; 8 import tagion.basic.Types : Buffer, isBufferType; 9 import tagion.basic.tagionexceptions : TagionException; 10 11 enum HEX_SEPARATOR = '_'; 12 13 @safe Buffer decode(const(char[]) hex) pure { 14 if (hex.replace(HEX_SEPARATOR, "").length % 2 != 0) { 15 throw new TagionException("Hex string length not even"); 16 } 17 int to_hex(const(char) c) { 18 if ((c >= '0') && (c <= '9')) { 19 return cast(ubyte)(c - '0'); 20 } 21 else if ((c >= 'a') && (c <= 'f')) { 22 return c - 'a' + 10; 23 } 24 else if ((c >= 'A') && (c <= 'F')) { 25 return cast(ubyte)(c - 'A') + 10; 26 } 27 throw new TagionException("Bad char '" ~ c ~ "'"); 28 } 29 30 immutable buf_size = hex.length / 2; 31 ubyte[] result = new ubyte[buf_size]; 32 uint j; 33 bool event; 34 ubyte part; 35 foreach (c; hex) { 36 if (c != HEX_SEPARATOR) { 37 part <<= 4; 38 part |= to_hex(c); 39 40 if (event) { 41 result[j] = part; 42 part = 0; 43 j++; 44 } 45 event = !event; 46 } 47 } 48 return result.idup; 49 } 50 51 /++ 52 + Converts on the first part of the buffer to a Hex string 53 + Used for debugging 54 + 55 + Params: 56 + buf = is a buffer type like a byte array 57 + Returns: 58 + The 16 first hex digits of the buffer 59 +/ 60 @safe 61 string cutHex(BUF)(BUF buf) pure if (isBufferType!BUF) { 62 import std.format; 63 import std.algorithm : min; 64 65 enum LEN = ulong.sizeof; 66 return format!"%(%02x%)"(buf[0 .. min(LEN, buf.length)]); 67 } 68 69 @safe 70 Buffer xor(scope const(ubyte[]) a, scope const(ubyte[]) b) pure nothrow 71 in { 72 assert(a.length == b.length); 73 assert(a.length % ulong.sizeof == 0); 74 } 75 do { 76 import tagion.utils.Gene : gene_xor; 77 78 const _a = cast(const(ulong[])) a; 79 const _b = cast(const(ulong[])) b; 80 return (() @trusted => cast(Buffer) gene_xor(_a, _b))(); 81 } 82 83 @nogc @safe 84 void xor(ref scope ubyte[] result, scope const(ubyte[]) a, scope const(ubyte[]) b) pure nothrow 85 in { 86 assert(a.length == b.length); 87 assert(a.length % ulong.sizeof == 0); 88 } 89 do { 90 import tagion.utils.Gene : gene_xor; 91 92 const _a = cast(const(ulong[])) a; 93 const _b = cast(const(ulong[])) b; 94 auto _result = cast(ulong[]) result; 95 gene_xor(_result, _a, _b); 96 } 97 98 @safe 99 Buffer xor(Range)(scope Range range) pure if (isInputRange!Range && is(ElementType!Range : const(ubyte[]))) 100 in (!range.empty) 101 do { 102 import std.array : array; 103 import std.range : tail; 104 105 scope result = new ubyte[range.front.length]; 106 range.each!((rhs) => xor(result, result, rhs)); 107 return result.idup; 108 }