This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

| Safe sprintf Submitted by

Here's a safe version of sprintf called format. Unlike sprintf, it won't produce buffer overflows and doesn't require the caller to allocate and deallocate the output buffer. The return value is an std::string that will be deallocated automatically when the last reference to it is dropped. The function is optimized for short strings but will work correctly for strings up to 1e6 bytes in length. This code is part of the Graphics3D library and may be used under the terms of that license (which is similar to the MIT/Berkley "don't sue me" license). Example usage:

      int month = 7, day = 26, year = 76;
      std::string name = "Birthday";
      std::string result =
             format("%s = %d-%02d-%02d\n", f.c_str(), month, day, year);

Morgan McGuire

Download Associated File: safesprintf.c (2,088 bytes)

    Here's a safe version of sprintf called format.  Unlike sprintf, it
    won't produce buffer overflows and doesn't require the caller to
    allocate and deallocate the output buffer.  The return value is an
    std::string that will be deallocated automatically when the last
    reference to it is dropped.  The function is optimized for short
    strings but will work correctly for strings up to 1e6 bytes in length.

    This code is part of the <A HREF="http://graphics3d.com/cpp">Graphics3D
    library</A> and may be used under the terms of that license (which is
    similar to the MIT/Berkley "don't sue me" license).

    Example usage:
      int month = 7, day = 26, year = 76;
      std::string name = "Birthday";
      std::string result =
             format("%s = %d-%02d-%02d\n", f.c_str(), month, day, year);

    Morgan McGuire
    matrix@graphics3d.com

    #include <string>
    #include <stdio.h>
    #include <cstdarg>
    #ifdef _WIN32
        #include <windows.h>
    #else
        #include <varargs.h>
    #endif

    std::string __cdecl format(const char* fmt ...) {
    	va_list argList;
        va_start(argList, fmt);
        std::string result = vformat(fmt, argList);
        va_end(argList);

        return result;
    }

    std::string vformat(const char *fmt, va_list argPtr) {
        // We draw the line at a 1MB string.
        const int maxSize = 1000000;

        // If the string is less than 161 characters,
        // allocate it on the stack because this saves
        // the malloc/free time.
        const int bufSize = 161;
    	char stackBuffer[bufSize];

        int attemptedSize = bufSize - 1;

        int numChars = vsnprintf(stackBuffer, attemptedSize, fmt, argPtr);

        if (numChars >= 0) {
            // Got it on the first try.
            return std::string(stackBuffer);
        }

        // Now use the heap.
        char* heapBuffer = NULL;

        while ((numChars == -1) && (attemptedSize < maxSize)) {
            // Try a bigger size
            attemptedSize *= 2;
            heapBuffer = (char*)realloc(heapBuffer, attemptedSize + 1);
            numChars = vsnprintf(heapBuffer, attemptedSize, fmt, argPtr);
        }

        std::string result = std::string(heapBuffer);

        free(heapBuffer);

        return result;

    }

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.