Skip to content

Commit

Permalink
ProcessRotateLeft: optimisations
Browse files Browse the repository at this point in the history
  • Loading branch information
arekbulski committed Apr 5, 2018
1 parent d705af9 commit 57e1b3b
Showing 1 changed file with 89 additions and 17 deletions.
106 changes: 89 additions & 17 deletions KaitaiStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ public KaitaiStream(byte[] data) : base(new MemoryStream(data))
/// </summary>
static readonly bool IsLittleEndian = BitConverter.IsLittleEndian;

static KaitaiStream()
{
compute_single_rotations();
}

#endregion

#region Stream positioning
Expand Down Expand Up @@ -520,40 +525,107 @@ public byte[] ProcessXor(byte[] data, byte[] key)
int kl = key.Length;
byte[] result = new byte[dl];

for (int i = 0, j = 0; i < dl; i++, j = i % kl)
for (int i = 0; i < dl; i++)
{
result[i] = (byte)(data[i] ^ key[j]);
result[i] = (byte)(data[i] ^ key[i % kl]);
}
return result;
}

/// <summary>
/// Used internally.
/// </summary>
private static byte[][] precomputed_single_rotations;

/// <summary>
/// Used internally.
/// </summary>
private static void compute_single_rotations()
{
precomputed_single_rotations = new byte[8][];
for (int amount = 1; amount < 8; amount++)
{
byte[] translate = new byte[256];
for (int i = 0; i < 256; i++)
{
// formula taken from: http://stackoverflow.com/a/812039
translate[i] = (byte) ((i << amount) | (i >> (8 - amount)));
}
precomputed_single_rotations[amount] = translate;
}
}

/// <summary>
/// Perform circular left rotation shift for a given data by a given amount of bits.
/// Pass a negative amount to rotate right.
/// WARNING: May return same byte array if amount is zero (modulo-wise).
/// </summary>
/// <param name="data">The data to rotate, as byte array</param>
/// <param name="amount">The amount to rotate by (in bits), as integer</param>
/// <param name="groupSize">The size of group in which rotation happens, as non-negative integer</param>
/// <param name="amount">The amount to rotate by (in bits), as integer, negative for right rotation</param>
/// <param name="groupSize">The size of group in which rotation happens, as positive integer</param>
public byte[] ProcessRotateLeft(byte[] data, int amount, int groupSize)
{
if (amount > 7 || amount < -7) throw new ArgumentException("Rotation of more than 7 cannot be performed.", "amount");
if (amount < 0) amount += 8; // Rotation of -2 is the same as rotation of +6
if (groupSize < 1)
throw new Exception("group size must be at least 1 to be valid");

amount = Mod(amount, groupSize * 8);
if (amount == 0)
return data;

int amount_bytes = amount / 8;
int dl = data.Length;
byte[] result = new byte[dl];

byte[] r = new byte[data.Length];
switch (groupSize)
if (groupSize == 1)
{
case 1:
for (int i = 0; i < data.Length; i++)
byte[] translate = precomputed_single_rotations[amount];

for (int i = 0; i < dl; i++)
{
result[i] = translate[data[i]];
}
return result;
}

if (dl % groupSize != 0)
throw new Exception("data length must be a multiple of group size");

if (amount % 8 == 0)
{
int[] indices = new int[groupSize];
for (int i = 0; i < groupSize; i++)
{
indices[i] = (i + amount_bytes) % groupSize;
}
for (int i = 0; i < dl; i += groupSize)
{
for (int k = 0; k < groupSize; k++)
{
byte bits = data[i];
// http://stackoverflow.com/a/812039
r[i] = (byte) ((bits << amount) | (bits >> (8 - amount)));
result[i+k] = data[i + indices[k]];
}
break;
default:
throw new NotImplementedException(string.Format("Unable to rotate a group of {0} bytes yet", groupSize));
}
return result;
}

{
int amount1 = amount % 8;
int amount2 = 8 - amount1;
int[] indices1 = new int[groupSize];
int[] indices2 = new int[groupSize];
for (int i = 0; i < groupSize; i++)
{
indices1[i] = (i + amount_bytes) % groupSize;
indices2[i] = (i + 1 + amount_bytes) % groupSize;
}
for (int i = 0; i < dl; i += groupSize)
{
for (int k = 0; k < groupSize; k++)
{
result[i+k] = (byte) ((data[i + indices1[k]] << amount1) | (data[i + indices2[k]] >> amount2));
}
}
return result;
}
return r;
}

/// <summary>
Expand Down

0 comments on commit 57e1b3b

Please sign in to comment.