views:

314

answers:

1

I am have written the following code below to encode a bitarray into custom base32 encoding string. My idea is user can mix the order of base32 array as per requirement and can add similar looking characters like I and 1 etc.

My intention of asking the question is: Is the code written in an appropriate manner or it lacks some basics. As far as i know it is generating the output as per the requirment, however i want to just validate the code here. If there are flaws do let me know.

A user will have a string which needs to be base32 encoded. So in his function he would call it this way.

BitArray ba = new BitArray(Encoding.UTF8.GetBytes(CustomString));
GenerateBase32FromString(ba);

Now the GenerateBase32FromString is as below

static string GenerateStringFromKey(BitArray ba)
{
    try
    {
        // user will modify the order as per requirement.
        char[] cProdKeyPoss = "ABGCD1EF2HI3KL4MN5PQ6RS7TV8WX9YZ".ToCharArray();
        StringBuilder finalstring = new StringBuilder();
        // add zero value bits to round off to multiple of 5
        //ba.Length = ba.Length + (5-(ba.Length % 5));
        // remove bits to round off to multiple of 5
        ba.Length = ba.Length - (ba.Length % 5);
        Console.WriteLine("ba.length = " + ba.Length.ToString());

        for (int i = 0; i < ba.Length; i = i + 5)
        {
            int[] bitvalue = { 0, 0, 0, 0, 0 };

            if (ba.Get(i) == true)
                bitvalue[0] = 1;

            if (ba.Get(i + 1) == true)
                bitvalue[1] = 1;

            if (ba.Get(i + 2) == true)
                bitvalue[2] = 1;

            if (ba.Get(i + 3) == true)
                bitvalue[3] = 1;

            if (ba.Get(i + 4) == true)
                bitvalue[4] = 1;

            int temp = (16 * bitvalue[0]) + (8 * bitvalue[1]) + (4 * bitvalue[2]) + (2 * bitvalue[3]) + (bitvalue[4]);
            finalstring.Append(cProdKeyPoss[temp].ToString());
        }
        Console.WriteLine(finalstring.ToString());
        return finalstring.ToString();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
        return null;
    }
}

I have kept both the options where i will chop the bits to round of to multiple of 5 or will add additional zero value bits to make it multiple of 5.

+2  A: 

A few suggestions:

  • You don't have any idea of "padding" - so you can't
  • Pass the key characters in as a parameter to the method. You can have an overload for a "default" one if you want
  • Either give the StringBuilder a capacity to start with, or create a char array of the right length and create the string directly from that
  • Catching Exception is almost always a bad idea, and it certainly is here. Any exception would be due to a bug in this code, so just let it bubble up the stack
  • Comparisons with "true" always look smelly to me, and I personally put if/for/while/etc statement bodies in blocks even for single statements, so I would have

    if (ba.Get(i))
    {
        bitValue[0] = 1;
    }
    
  • There's no real point in having the bit array to start with. Why not just add to a value which starts at 0?

    if (ba.Get(i))
    {
        temp += 16;
    }
    // etc
    
  • Repeated code like that suggests a loop:

    int temp = 0;
    for (int j = 0; j < 5; j++)
    {
        if (ba.Get(i + j))
        {
            // This could just be "1 << j" if you don't mind the
            // results being different to your current code
            temp += 1 << (4 - j);
        }
    }
    
  • Library methods shouldn't write to the console
  • Don't call ToString when you've got the right character - just call Append(char) (or set the value in the result char array).
Jon Skeet
Thanks Jon for valuable comments. The loop logic really shortened my code. You first comment indicated about padding. Since i would not be aware what length would be the string in terms of bits be i thought the approach of either adding or chopping off the bits should be there. Though i can add an argument asking use to decide either of the two options. Writing to console was just to check the output since was using console app for testing.
Kavitesh Singh
Also if you could explain why having an exception in the code is wrong. What i am trying to do here is, if things work normally then it would return the string in base-32 format. If incase there is some problem and exception is raised, i would return a null string and can add a messagebox showing the exception details. Would it be wrong approach?
Kavitesh Singh
@Kavitesh: The point is that at the point of encoding you *do* know the length of the string - so you can use padding to make sure you always end up with a round number of characters. Look at how base64 uses padding as an example. As for the exception: this is a relatively low level routine. It shouldn't make the decision about how an exception is handled. That's up to the calling application - which almost certainly shouldn't just catch "Exception" either, except at the topmost level. Usually anything low down the stack should only catch specific exceptions it can genuinely *handle*.
Jon Skeet