User:Shimmy/Variable-length quantity: Difference between revisions

From Rosetta Code
Content added Content deleted
(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.Collections.Generic;
using System.IO;
using System.Linq;


public static class VarLenQuantity
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 array = new byte[8];
var index = 0;
var buffer = ToVlqCollection(integer)
uint buffer = 0;
byte current;
.SkipWhile(b => b == 0)
.Reverse()
do
.ToArray();
{
Array.Copy(buffer, array, buffer.Length);
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 = 7;
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;
yield return (byte)buffer;
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>