User:Shimmy/Variable-length quantity: Difference between revisions
Content deleted Content added
Created page with "<lang csharp>namespace Vlq { using System; using System.Collections.Generic; using System.Linq; public static class VarLenQuantity { public static ulong ToVlq(u..." |
No edit summary |
||
Line 2: | Line 2: | ||
{ |
{ |
||
using System; |
using System; |
||
using System. |
using System.IO; |
||
using System.Linq; |
|||
public static class |
public static class VariableLengthQuantity |
||
{ |
{ |
||
/// <summary> |
|||
public static ulong ToVlq(ulong integer) |
|||
/// Reads a 7-bit encoded variable-length quantity from binary and return it as integer. |
|||
/// </summary> |
|||
/// <returns></returns> |
|||
public uint ReadVariableLengthQuantity(BinaryReader reader) |
|||
{ |
{ |
||
var |
var index = 0; |
||
uint buffer = 0; |
|||
byte current; |
|||
.SkipWhile(b => b == 0) |
|||
do |
|||
{ |
|||
if (index++ == 8) |
|||
throw new FormatException("Could not read variable-length quantity from provided stream."); |
|||
return BitConverter.ToUInt64(array, 0); |
|||
} |
|||
buffer <<= 7; |
|||
current = reader.ReadByte(); |
|||
buffer |= (current & 0x7FU); |
|||
} while ((current & 0x80) != 0); |
|||
return buffer; |
|||
public static ulong FromVlq(ulong integer) |
|||
{ |
|||
var collection = BitConverter.GetBytes(integer).Reverse(); |
|||
return FromVlqCollection(collection); |
|||
} |
} |
||
/// <summary> |
|||
public static IEnumerable<byte> ToVlqCollection(ulong integer) |
|||
/// Writes the specified integer as a 7-bit encoded variable-length quantity. |
|||
/// </summary> |
|||
/// <param name="integer"></param> |
|||
public void WriteVariableLengthQuantity(BinaryWriter writer, ulong integer) |
|||
{ |
{ |
||
if (integer > Math.Pow(2, 56)) |
if (integer > Math.Pow(2, 56)) |
||
throw new OverflowException("Integer exceeds max value."); |
throw new OverflowException("Integer exceeds max value."); |
||
var index = |
var index = 3; |
||
var significantBitReached = false; |
var significantBitReached = false; |
||
var mask = 0x7fUL << (index * 7); |
var mask = 0x7fUL << (index * 7); |
||
Line 41: | Line 50: | ||
if (index > 0) |
if (index > 0) |
||
buffer |= 0x80; |
buffer |= 0x80; |
||
writer.Write((byte)buffer); |
|||
} |
} |
||
mask >>= 7; |
mask >>= 7; |
||
index--; |
index--; |
||
} |
} |
||
} |
|||
if (!significantBitReached && index < 0) |
|||
writer.Write(new byte()); |
|||
public static ulong FromVlqCollection(IEnumerable<byte> vlq) |
|||
{ |
|||
ulong integer = 0; |
|||
var significantBitReached = false; |
|||
using (var enumerator = vlq.GetEnumerator()) |
|||
{ |
|||
int index = 0; |
|||
while (enumerator.MoveNext()) |
|||
{ |
|||
var buffer = enumerator.Current; |
|||
if (buffer > 0 || significantBitReached) |
|||
{ |
|||
significantBitReached = true; |
|||
integer <<= 7; |
|||
integer |= (buffer & 0x7fUL); |
|||
} |
|||
if (++index == 8 || (significantBitReached && (buffer & 0x80) != 0x80)) |
|||
break; |
|||
} |
|||
} |
|||
return integer; |
|||
} |
|||
public static void Main() |
|||
{ |
|||
var integers = new ulong[] { 0x7fUL << 7 * 7, 0x80, 0x2000, 0x3FFF, 0x4000, 0x200000, 0x1fffff }; |
|||
foreach (var original in integers) |
|||
{ |
|||
Console.WriteLine("Original: 0x{0:X}", original); |
|||
//collection |
|||
var seq = ToVlqCollection(original); |
|||
Console.WriteLine("Sequence: 0x{0}", seq.Select(b => b.ToString("X2")).Aggregate(string.Concat)); |
|||
var decoded = FromVlqCollection(seq); |
|||
Console.WriteLine("Decoded: 0x{0:X}", decoded); |
|||
//ints |
|||
var encoded = ToVlq(original); |
|||
Console.WriteLine("Encoded: 0x{0:X}", encoded); |
|||
decoded = FromVlq(encoded); |
|||
Console.WriteLine("Decoded: 0x{0:X}", decoded); |
|||
Console.WriteLine(); |
|||
} |
|||
Console.WriteLine("Press any key to continue..."); |
|||
Console.ReadKey(); |
|||
} |
} |
||
} |
} |
||
}</lang> |
|||
}</lang>output<lang>Original: 0xFE000000000000 |
|||
Sequence: 0xFF80808080808000 |
|||
Decoded: 0xFE000000000000 |
|||
Encoded: 0xFF80808080808000 |
|||
Decoded: 0xFE000000000000 |
|||
Original: 0x80 |
|||
Sequence: 0x8100 |
|||
Decoded: 0x80 |
|||
Encoded: 0x8100 |
|||
Decoded: 0x80 |
|||
Original: 0x2000 |
|||
Sequence: 0xC000 |
|||
Decoded: 0x2000 |
|||
Encoded: 0xC000 |
|||
Decoded: 0x2000 |
|||
Original: 0x3FFF |
|||
Sequence: 0xFF7F |
|||
Decoded: 0x3FFF |
|||
Encoded: 0xFF7F |
|||
Decoded: 0x3FFF |
|||
Original: 0x4000 |
|||
Sequence: 0x818000 |
|||
Decoded: 0x4000 |
|||
Encoded: 0x818000 |
|||
Decoded: 0x4000 |
|||
Original: 0x200000 |
|||
Sequence: 0x81808000 |
|||
Decoded: 0x200000 |
|||
Encoded: 0x81808000 |
|||
Decoded: 0x200000 |
|||
Original: 0x1FFFFF |
|||
Sequence: 0xFFFF7F |
|||
Decoded: 0x1FFFFF |
|||
Encoded: 0xFFFF7F |
|||
Decoded: 0x1FFFFF |
|||
Press any key to continue...</lang> |
Revision as of 00:31, 30 October 2014
<lang csharp>namespace Vlq {
using System; using System.IO;
public static class VariableLengthQuantity { /// <summary> /// Reads a 7-bit encoded variable-length quantity from binary and return it as integer. /// </summary> /// <returns></returns> public uint ReadVariableLengthQuantity(BinaryReader reader) { var index = 0; uint buffer = 0; byte current; do { if (index++ == 8) throw new FormatException("Could not read variable-length quantity from provided stream.");
buffer <<= 7;
current = reader.ReadByte(); buffer |= (current & 0x7FU); } while ((current & 0x80) != 0);
return buffer; }
/// <summary> /// Writes the specified integer as a 7-bit encoded variable-length quantity. /// </summary> /// <param name="integer"></param> public void WriteVariableLengthQuantity(BinaryWriter writer, ulong integer) { if (integer > Math.Pow(2, 56)) throw new OverflowException("Integer exceeds max value.");
var index = 3; var significantBitReached = false; var mask = 0x7fUL << (index * 7); while (index >= 0) { var buffer = (mask & integer); if (buffer > 0 || significantBitReached) { significantBitReached = true; buffer >>= index * 7; if (index > 0) buffer |= 0x80; writer.Write((byte)buffer); } mask >>= 7; index--; }
if (!significantBitReached && index < 0) writer.Write(new byte()); } }
}</lang>