all tasks
This commit is contained in:
parent
b83f433714
commit
68f8f3e56b
14735 changed files with 178959 additions and 0 deletions
85
Task/Variable-length-quantity/D/variable-length-quantity.d
Normal file
85
Task/Variable-length-quantity/D/variable-length-quantity.d
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
import std.stdio, std.string, std.file, std.algorithm;
|
||||
|
||||
/// Variable length quantity (unsigned long, max 63-bit).
|
||||
struct VLQ {
|
||||
ulong value;
|
||||
|
||||
// This allows VLQ to work like an ulong.
|
||||
alias value this;
|
||||
|
||||
uint extract(in ubyte[] v) pure
|
||||
in {
|
||||
assert(v.length > 0);
|
||||
} body {
|
||||
immutable limit = min(v.length - 1, 8);
|
||||
ulong t = 0;
|
||||
size_t idx = 0;
|
||||
while ((idx < limit) && ((v[idx] & 0x80) > 0))
|
||||
t = (t << 7) | (0x7f & v[idx++]);
|
||||
if (idx > limit)
|
||||
throw new Exception(
|
||||
"Too large for ulong or invalid format.");
|
||||
else
|
||||
value = (t << 7) | v[idx];
|
||||
return idx + 1;
|
||||
}
|
||||
|
||||
VLQ from(in ubyte[] v) pure {
|
||||
extract(v);
|
||||
return this;
|
||||
}
|
||||
|
||||
@property ubyte[] toVLQ() const pure {
|
||||
ubyte[] v = [0x7f & value];
|
||||
for (ulong k = value >>> 7; k > 0; k >>>= 7)
|
||||
v ~= (k & 0x7f) | 0x80;
|
||||
if (v.length > 9)
|
||||
throw new Exception("Too large value.");
|
||||
v.reverse();
|
||||
return v;
|
||||
}
|
||||
|
||||
static ulong[] split(in ubyte[] b) pure {
|
||||
ulong[] res;
|
||||
VLQ v;
|
||||
for (size_t i = 0; i < b.length; ) {
|
||||
i += v.extract(b[i .. $]);
|
||||
res ~= v.value;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
string toString() const /*pure nothrow*/ {
|
||||
return format("(%(%02X:%))", this.toVLQ);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void main() { // VLQ demo code.
|
||||
VLQ a = VLQ(0x7f),
|
||||
b = VLQ(0x4000),
|
||||
c;
|
||||
writefln("a:%8x = %s\nb:%8x = %s\nc:%8x = %s",
|
||||
a.value, a, b.value, b, c.value, c);
|
||||
|
||||
// Some operations.
|
||||
c = (a + 1) * b;
|
||||
a = c - 1;
|
||||
b = VLQ().from(a.toVLQ);
|
||||
a <<= 1;
|
||||
|
||||
// Convert ulong to octet sequence.
|
||||
writefln("\na:%8x = %s\nb:%8x = %s\nc:%8x = %s",
|
||||
a.value, a, b.value, b, c.value, c);
|
||||
|
||||
// Write them to a binary file.
|
||||
std.file.write("vlqtest.bin", a.toVLQ ~ b.toVLQ ~ c.toVLQ);
|
||||
|
||||
// Read them back.
|
||||
const buf = cast(ubyte[])std.file.read("vlqtest.bin");
|
||||
writefln("\nFile length: %d bytes.", buf.length);
|
||||
|
||||
// Convert octet sequence to ulongs.
|
||||
foreach (immutable i, immutable v; VLQ.split(buf))
|
||||
writefln("%d:%8x = %s", i + 1, v, VLQ(v));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue