4

I can't seem to find if there's a built-in way to do a circular bitshift of a byte array, what C's ROL and ROR used to do with a single byte?

Let me explain, say, I have an array (in binary):

[0] = 11001110
[1] = 01000100
[2] = 10100001

and then if I want to do ROL_Array(1 bit) or move bits 1 bit to the left, I'd get:

[0] = 10011100
[1] = 10001001
[2] = 01000011

or, if I want to do ROR_Array(2 bits) or move bits 2 bits to the right, I'd get:

[0] = 00110011
[1] = 01010001
[2] = 10101000
ahmd0
  • 16,633
  • 33
  • 137
  • 233

1 Answers1

3

This is not as simple as you'd think. Here's a quick version before this thread gets closed:

public static byte[] ROL_ByteArray(byte[] arr, int nShift)
{
    //Performs bitwise circular shift of 'arr' by 'nShift' bits to the left
    //RETURN:
    //      = Result
    byte[] resArr = new byte[arr.Length];

    if(arr.Length > 0)
    {
        int nByteShift = nShift / (sizeof(byte) * 8);   //Adjusted after @dasblinkenlight's correction
        int nBitShift = nShift % (sizeof(byte) * 8);

        if (nByteShift >= arr.Length)
            nByteShift %= arr.Length;

        int s = arr.Length - 1;
        int d = s - nByteShift;

        for (int nCnt = 0; nCnt < arr.Length; nCnt++, d--, s--)
        {
            while (d < 0)
                d += arr.Length;
            while (s < 0)
                s += arr.Length;

            byte byteS = arr[s];

            resArr[d] |= (byte)(byteS << nBitShift);
            resArr[d > 0 ? d - 1 : resArr.Length - 1] |= (byte)(byteS >> (sizeof(byte) * 8 - nBitShift));


        }
    }

    return resArr;
}

and here's a test:

byte[] arr = new byte[] {
    Convert.ToByte("11001110", 2),
    Convert.ToByte("01000100", 2),
    Convert.ToByte("10100001", 2),
    };

byte[] arr2 = Auth.ROL_ByteArray(arr, 1);

string sss = "";
for (int i = 0; i < arr2.Length; i++)
    sss += Convert.ToString(arr2[i], 2) + ", ";

Debug.WriteLine(sss);
ahmd0
  • 16,633
  • 33
  • 137
  • 233
  • What's the purpose of multiplying 8 by `sizeof(byte)`, given that .NET specifies a value range of 0..255? – Sergey Kalinichenko Mar 22 '13 at 10:20
  • @dasblinkenlight: It is just my way of calculating number of bits in a byte. You can hardcode that value if you'd like. – ahmd0 Mar 22 '13 at 17:59
  • How's your hardcoding of 8 differ from anyone else's hardcoding of 8? You use 8 by itself everywhere except the shift; the reason it even works is that `sizeof(byte)` is *guaranteed* to be `1`, so why bother bringing in an operation that requires unsafe context? – Sergey Kalinichenko Mar 22 '13 at 18:04
  • @dasblinkenlight: OK, you're right I used 8 in other places. As I posted above -- the code was constructed rather quickly. – ahmd0 Mar 22 '13 at 18:15
  • 1
    You might want to explicitly handle special cases, e.g. when `nShift % 8 == 0` and when `nShift % ( 8 * arr.Length ) == 0` if this is going into a general purpose library. – HABO Mar 22 '13 at 19:18
  • @HABO: You're welcome to optimize it. I admit that I haven't done that. The code above is the first draft. – ahmd0 Mar 23 '13 at 21:56