Posts Tagged ‘c++’

The Worst C++ Code Ever

Yesterday morning, I overheard a couple co-workers and Cecil talking about problems they were having compiling their software this morning. I popped over to Cecil’s desk to take a look, since I like seeing messed up problems. It took about three seconds flat to diagnose the problem:

/wsimages/m_Symbol.png

It looks like someone has #define’d m_Symbol.

Someone had defined m_Symbol as a preprocessor macro. Why on earth would that be? A bit more digging determined that a co-worker had decided to move a bunch of variables in a library class into a small class, to consolidate them. Unfortunately, this class was written with all of these member variables as public, so he decided that writing a bunch of preprocessor macros would be the only way to allow everyone to keep working despite his changes:

#define m_Symbol    m_Sym.m_Type
#define m_SymSize   m_Sym.m_Size
...

He tested it by building one of our larger applications, and then assumed if it worked there it would work everywhere. This was bad code.

The correct possible solutions involved more work:

  • Re-write everyone’s code to use the new classes.
  • Use accessor methods and keep data private so that it can be rearranged in the future.

Of course, both of these would involve a lot of code re-writing. An automated semi-intelligent find and replace could take care of at least 80% of the cases, but some hand writing would need to be done. Since it involved more work, he didn’t do it. He plans to someday fix this when he has a spare programmer lying around.

BAH.

Coding everything in Python would be the best alternative.

COMImageLib

Once upon a time, in a galaxy far far away, I was writting a small piece of code to capture a screenshot in Windows. It wasn’t difficult to capture the screenshot, nor convert it to a device independant bitmap, nor output it as a .bmp file. But bmp files are huge, and these screenshots were going to be uploaded to a software issue tracking website. So, I decided to convert them to the much more compressable PNG image file format.

It would have been socially inacceptable for me to link libpng and zlib into the very low-level dll that this image capturing was being put into. I decided to make a COM module which would wrap libpng and zlib together. This way, the existence of the COM module could be detected and PNG files used, otherwise BMP files could be used as a last resort measure.

All this COM module can do is convert a BMP file to a PNG file. I hardly wrote any actual code, though. I yoinked the BMP -> PNG conversion from the web page of Jason Summers, and wrote a dead simple interface:

interface IPngImage : IDispatch
{
    [id(1), helpstring("method ConvertBMPToPNG")]
        HRESULT ConvertBMPToPNG([in] BSTR bsBMP, [in] BSTR bsPNG);
};

Happily this was all I needed. However, if you need something different, this COM module provides a nice framework for doing any work with PNG files since it statically links with pre-built libpng and zlib libraries (included in the source).

Source, Binary

Dictionary String Sorting

The following two functions define a method of comparing two strings. The method is similar to that implemented by strcmp, but differs in two ways. Whitespace within the strings is ignored, and numbers are compared numerically rather than character by character. ’10′ is greater than ’5′, for example.

/**
 * Determines whether a character is whitespace or not.
 */
int iswhitespace(char x)
{
    return x == ' ' || x == '\\n' || x == '\\r' || x == '\\t';
}

/**
 * qsort comparison function for 'dictionary' like string sorting.  Differs
 * from strcmp in two important ways.  1) "Baby Zoe" comes after "Babyface",
 * whitespace is ignored.  2) "5" comes before "10", numbers are sorted
 * numerically.
 *
 * @param       pStr1   Sort parameter 1. (ptr to char)
 * @param       pStr2   Sort parameter 2. (ptr to char)
 * @return      {-1, 0, 1} if pStr1 is {less than, equal to, greather than}
 *              pStr2.
 */
int dictionarySort(void* pStr1, void* pStr2)
{
    char* a = pStr1;
    char* b = pStr2;

    for (;;)
    {
        if (*a == *b && *a == '\\0')
            return 0;
        else if (*a == '\\0')
            return -1;
        else if (*b == '\\0')
            return 1;

        while (iswhitespace(*a) && *a != '\\0') a++;
        while (iswhitespace(*b) && *b != '\\0') b++;

        if (*a >= '0' && *a <= '9' &&
            *b >= '0' && *b <= '9')
        {
            /* a and b look to be pointing towards the start of numeric
             * strings! :) 
             */
            int nNumericA = atoi(a);
            int nNumericB = atoi(b);

            if (nNumericA < nNumericB)
                return -1;
            else if (nNumericA > nNumericB)
                return 1;

            while (*a >= '0' && *a <= '9' && *a != '\\0') a++;
            while (*b >= '0' && *b <= '9' && *b != '\\0') b++;
        }

        if (*a < *b)
            return -1;
        else if (*a > *b)
            return 1;

        a++;
        b++;
    }

    /* shut off compiler warnings. */
    return 0;
}