A variable-length unsigned/signed integer using base128 encoding. 1-byte groups consist of 1-bit flag of continuation and 7-bit value chunk, and are ordered "least significant group first", i.e. in "little-endian" manner.
This particular encoding is specified and used in:
More information on this encoding is available at https://en.wikipedia.org/wiki/LEB128
This particular implementation supports serialized values to up 8 bytes long.
This page hosts a formal specification of Variable length quantity, unsigned/signed integer, base128, little-endian using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.
All parsing code for C# generated by Kaitai Struct depends on the C# runtime library. You have to install it before you can parse data.
The C# runtime library is available in the NuGet Gallery. Installation instructions can also be found there.
Parse a local file and get structure in memory:
var data = VlqBase128Le.FromFile("path/to/local/file.bin");
Or parse structure from a byte array:
byte[] someArray = new byte[] { ... };
var data = new VlqBase128Le(new KaitaiStream(someArray));
After that, one can get various attributes from the structure by accessing properties like:
data.Value // => Resulting unsigned value as normal integer
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
using System.Collections.Generic;
namespace Kaitai
{
/// <summary>
/// A variable-length unsigned/signed integer using base128 encoding. 1-byte groups
/// consist of 1-bit flag of continuation and 7-bit value chunk, and are ordered
/// "least significant group first", i.e. in "little-endian" manner.
///
/// This particular encoding is specified and used in:
///
/// * DWARF debug file format, where it's dubbed "unsigned LEB128" or "ULEB128".
/// <https://dwarfstd.org/doc/dwarf-2.0.0.pdf> - page 139
/// * Google Protocol Buffers, where it's called "Base 128 Varints".
/// <https://protobuf.dev/programming-guides/encoding/#varints>
/// * Apache Lucene, where it's called "VInt"
/// <https://lucene.apache.org/core/3_5_0/fileformats.html#VInt>
/// * Apache Avro uses this as a basis for integer encoding, adding ZigZag on
/// top of it for signed ints
/// <https://avro.apache.org/docs/current/spec.html#binary_encode_primitive>
///
/// More information on this encoding is available at <https://en.wikipedia.org/wiki/LEB128>
///
/// This particular implementation supports serialized values to up 8 bytes long.
/// </summary>
public partial class VlqBase128Le : KaitaiStruct
{
public static VlqBase128Le FromFile(string fileName)
{
return new VlqBase128Le(new KaitaiStream(fileName));
}
public VlqBase128Le(KaitaiStream p__io, KaitaiStruct p__parent = null, VlqBase128Le p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root ?? this;
f_len = false;
f_value = false;
f_signBit = false;
f_valueSigned = false;
_read();
}
private void _read()
{
_groups = new List<Group>();
{
var i = 0;
Group M_;
do {
M_ = new Group(m_io, this, m_root);
_groups.Add(M_);
i++;
} while (!(!(M_.HasNext)));
}
}
/// <summary>
/// One byte group, clearly divided into 7-bit "value" chunk and 1-bit "continuation" flag.
/// </summary>
public partial class Group : KaitaiStruct
{
public static Group FromFile(string fileName)
{
return new Group(new KaitaiStream(fileName));
}
public Group(KaitaiStream p__io, VlqBase128Le p__parent = null, VlqBase128Le p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_hasNext = m_io.ReadBitsIntBe(1) != 0;
_value = m_io.ReadBitsIntBe(7);
}
private bool _hasNext;
private ulong _value;
private VlqBase128Le m_root;
private VlqBase128Le m_parent;
/// <summary>
/// If true, then we have more bytes to read
/// </summary>
public bool HasNext { get { return _hasNext; } }
/// <summary>
/// The 7-bit (base128) numeric value chunk of this group
/// </summary>
public ulong Value { get { return _value; } }
public VlqBase128Le M_Root { get { return m_root; } }
public VlqBase128Le M_Parent { get { return m_parent; } }
}
private bool f_len;
private int _len;
public int Len
{
get
{
if (f_len)
return _len;
_len = (int) (Groups.Count);
f_len = true;
return _len;
}
}
private bool f_value;
private ulong _value;
/// <summary>
/// Resulting unsigned value as normal integer
/// </summary>
public ulong Value
{
get
{
if (f_value)
return _value;
_value = (ulong) (((ulong) ((((((((Groups[0].Value + (Len >= 2 ? (Groups[1].Value << 7) : 0)) + (Len >= 3 ? (Groups[2].Value << 14) : 0)) + (Len >= 4 ? (Groups[3].Value << 21) : 0)) + (Len >= 5 ? (Groups[4].Value << 28) : 0)) + (Len >= 6 ? (Groups[5].Value << 35) : 0)) + (Len >= 7 ? (Groups[6].Value << 42) : 0)) + (Len >= 8 ? (Groups[7].Value << 49) : 0)))));
f_value = true;
return _value;
}
}
private bool f_signBit;
private ulong _signBit;
public ulong SignBit
{
get
{
if (f_signBit)
return _signBit;
_signBit = (ulong) (((ulong) ((((ulong) (1)) << ((7 * Len) - 1)))));
f_signBit = true;
return _signBit;
}
}
private bool f_valueSigned;
private long _valueSigned;
/// <remarks>
/// Reference: <a href="https://graphics.stanford.edu/~seander/bithacks.html#VariableSignExtend">Source</a>
/// </remarks>
public long ValueSigned
{
get
{
if (f_valueSigned)
return _valueSigned;
_valueSigned = (long) (((long) ((((long) ((Value ^ SignBit))) - ((long) (SignBit))))));
f_valueSigned = true;
return _valueSigned;
}
}
private List<Group> _groups;
private VlqBase128Le m_root;
private KaitaiStruct m_parent;
public List<Group> Groups { get { return _groups; } }
public VlqBase128Le M_Root { get { return m_root; } }
public KaitaiStruct M_Parent { get { return m_parent; } }
}
}