public static long byte_array_to_long(byte[] b, bool unsigned)
{
long v = 0;
switch (b.Length)
{
case 0:
v = 0;
break;
case 2:
v = ((b[0] & 0xFF) << 8) + (b[1] & 0xFF);
v = (short)v; // Sign extend
if (v < 0 && unsigned)
{
throw new OtpErlangDecodeException("Value not unsigned: " + v);
}
break;
case 4:
v = ((b[0] & 0xFF) << 24) + ((b[1] & 0xFF) << 16)
+ ((b[2] & 0xFF) << 8) + (b[3] & 0xFF);
v = (int)v; // Sign extend
if (v < 0 && unsigned)
{
throw new OtpErlangDecodeException("Value not unsigned: " + v);
}
break;
default:
int i = 0;
byte c = b[i];
// Skip non-essential leading bytes
if (unsigned)
{
if (c < 0)
{
throw new OtpErlangDecodeException("Value not unsigned: " + b);
}
while (b[i] == 0)
{
i++; // Skip leading zero sign bytes
}
}
else
{
if (c == 0 || c == 0xFF) // Leading sign byte
{
i = 1;
// Skip all leading sign bytes
while (i < b.Length && b[i] == c)
{
i++;
}
if (i < b.Length)
{
// Check first non-sign byte to see if its sign
// matches the whole number's sign. If not one more
// byte is needed to represent the value.
if (((c ^ b[i]) & 0x80) != 0)
{
i--;
}
}
}
}
if (b.Length - i > 8)
{
// More than 64 bits of value
throw new OtpErlangDecodeException("Value does not fit in long: " + b);
}
// Convert the necessary bytes
for (v = c < 0 ? -1 : 0; i < b.Length; i++)
{
v = (long)((((ulong)v) << 8) | ((ulong)(b[i] & 0xFF)));
}
break;
}
return v;
}