using System;
using System.Runtime.CompilerServices;
namespace PKHeX.Core
{
///
/// 4-bit decimal encoding used by some Generation 1 save file values.
///
public static class BinaryCodedDecimal
{
///
/// Returns a 32-bit signed integer converted from bytes in a Binary Coded Decimal format byte array.
///
/// Input byte array to read from.
/// Offset to start reading at.
/// Length of array to read.
public static int ToInt32BE(byte[] input, int offset, int length)
{
var span = new ReadOnlySpan(input, offset, length);
return ToInt32BE(span);
}
///
public static int ToInt32BE(ReadOnlySpan input)
{
int result = 0;
foreach (var b in input)
PushDigits(ref result, b);
return result;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void PushDigits(ref int result, byte b) => result = (result * 100) + (10 * (b >> 4)) + (b & 0xf);
///
/// Returns the specified 32-bit signed integer value as an array of Binary Coded Decimal format bytes.
///
/// 32-bit signed integer to convert.
/// Desired size of returned array.
public static byte[] GetBytesBE(int value, int size)
{
byte[] data = new byte[size];
WriteBytesBE(data, value);
return data;
}
public static void WriteBytesBE(Span data, int value)
{
for (int i = 0; i < data.Length; i++)
{
int p = value % 100;
value /= 100;
data[^(1+i)] = (byte) (p / 10 << 4 | p % 10);
}
}
///
/// Big Endian instead of Little Endian
public static int ToInt32LE(byte[] data, int offset, int length)
{
var span = new ReadOnlySpan(data, offset, length);
return ToInt32LE(span);
}
///
public static int ToInt32LE(ReadOnlySpan input)
{
int result = 0;
for (int i = input.Length - 1; i >= 0; i--)
PushDigits(ref result, input[i]);
return result;
}
///
/// Little Endian instead of Big Endian
public static byte[] GetBytesLE(int value, int size)
{
byte[] data = new byte[size];
WriteBytesLE(data, value);
return data;
}
///
/// Writes the to the buffer.
///
public static void WriteBytesLE(Span data, int value)
{
for (int i = 0; i < data.Length; i++)
{
int p = value % 100;
value /= 100;
data[i] = (byte) (p / 10 << 4 | p % 10);
}
}
}
}