You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
jellyfin/Emby.Server.Implementations/Networking/IPNetwork/BigIntegerExt.cs

168 lines
5.3 KiB

using System;
using System.Collections.Generic;
using System.Numerics;
using System.Text;
namespace Emby.Server.Implementations.Networking.IPNetwork
{
/// <summary>
/// Extension methods to convert <see cref="BigInteger"/>
/// instances to hexadecimal, octal, and binary strings.
/// </summary>
public static class BigIntegerExtensions
{
/// <summary>
/// Converts a <see cref="BigInteger"/> to a binary string.
/// </summary>
/// <param name="bigint">A <see cref="BigInteger"/>.</param>
/// <returns>
/// A <see cref="string"/> containing a binary
/// representation of the supplied <see cref="BigInteger"/>.
/// </returns>
public static string ToBinaryString(this BigInteger bigint)
{
var bytes = bigint.ToByteArray();
var idx = bytes.Length - 1;
// Create a StringBuilder having appropriate capacity.
var base2 = new StringBuilder(bytes.Length * 8);
// Convert first byte to binary.
var binary = Convert.ToString(bytes[idx], 2);
// Ensure leading zero exists if value is positive.
if (binary[0] != '0' && bigint.Sign == 1)
{
base2.Append('0');
}
// Append binary string to StringBuilder.
base2.Append(binary);
// Convert remaining bytes adding leading zeros.
for (idx--; idx >= 0; idx--)
{
base2.Append(Convert.ToString(bytes[idx], 2).PadLeft(8, '0'));
}
return base2.ToString();
}
/// <summary>
/// Converts a <see cref="BigInteger"/> to a hexadecimal string.
/// </summary>
/// <param name="bigint">A <see cref="BigInteger"/>.</param>
/// <returns>
/// A <see cref="string"/> containing a hexadecimal
/// representation of the supplied <see cref="BigInteger"/>.
/// </returns>
public static string ToHexadecimalString(this BigInteger bigint)
{
return bigint.ToString("X");
}
/// <summary>
/// Converts a <see cref="BigInteger"/> to a octal string.
/// </summary>
/// <param name="bigint">A <see cref="BigInteger"/>.</param>
/// <returns>
/// A <see cref="string"/> containing an octal
/// representation of the supplied <see cref="BigInteger"/>.
/// </returns>
public static string ToOctalString(this BigInteger bigint)
{
var bytes = bigint.ToByteArray();
var idx = bytes.Length - 1;
// Create a StringBuilder having appropriate capacity.
var base8 = new StringBuilder(((bytes.Length / 3) + 1) * 8);
// Calculate how many bytes are extra when byte array is split
// into three-byte (24-bit) chunks.
var extra = bytes.Length % 3;
// If no bytes are extra, use three bytes for first chunk.
if (extra == 0)
{
extra = 3;
}
// Convert first chunk (24-bits) to integer value.
int int24 = 0;
for (; extra != 0; extra--)
{
int24 <<= 8;
int24 += bytes[idx--];
}
// Convert 24-bit integer to octal without adding leading zeros.
var octal = Convert.ToString(int24, 8);
// Ensure leading zero exists if value is positive.
if (octal[0] != '0')
{
if (bigint.Sign == 1)
{
base8.Append('0');
}
}
// Append first converted chunk to StringBuilder.
base8.Append(octal);
// Convert remaining 24-bit chunks, adding leading zeros.
for (; idx >= 0; idx -= 3)
{
int24 = (bytes[idx] << 16) + (bytes[idx - 1] << 8) + bytes[idx - 2];
base8.Append(Convert.ToString(int24, 8).PadLeft(8, '0'));
}
return base8.ToString();
}
/// <summary>
///
/// Reverse a Positive BigInteger ONLY
/// Bitwise ~ operator
///
/// Input : FF FF FF FF
/// Width : 4
/// Result : 00 00 00 00
///
///
/// Input : 00 00 00 00
/// Width : 4
/// Result : FF FF FF FF
///
/// Input : FF FF FF FF
/// Width : 8
/// Result : FF FF FF FF 00 00 00 00
///
///
/// Input : 00 00 00 00
/// Width : 8
/// Result : FF FF FF FF FF FF FF FF
///
/// </summary>
/// <param name="input"></param>
/// <param name="width"></param>
/// <returns></returns>
public static BigInteger PositiveReverse(this BigInteger input, int width)
{
var result = new List<byte>();
var bytes = input.ToByteArray();
var work = new byte[width];
Array.Copy(bytes, 0, work, 0, bytes.Length - 1); // Length -1 : positive BigInteger
for (int i = 0; i < work.Length; i++)
{
result.Add((byte)(~work[i]));
}
result.Add(0); // positive BigInteger
return new BigInteger(result.ToArray());
}
}
}