You are viewing an old version of the ionflux.org website! Please visit the new version 
here.
 
      Hexadecimal Output (C++)
      I often want to take a look at data which has been generated by some code I have
written, but which is not readable very well by humans. In the worst case, it 
may even contain characters which are not printable at all. For these 
situations, I have written some nice little functions which display arbitrary 
byte data in hexadecimal notation, much like in a hexadecimal editor. It is also
possible to view the hexadecimal representation side by side with the readable 
characters.
	Byte to Hexadecimal String Converter
	This snippet does the simple task of converting a string of bytes to a string of
hexadecimal numbers.
	#include <string>
#include <sstream>
#include <iomanip>
std::string make_hex(const std::string& inputData)
{
    std::ostringstream buffer;
    buffer << std::uppercase << std::right << std::setfill('0') << std::hex;
    for (unsigned int i = 0; i < inputData.size(); i++)
        buffer << std::setw(2) << int(static_cast<unsigned char>(inputData[i]));
    return buffer.str();
}
	Make Readable Text
	Some characters can be considered readable, even in a soup of random bytes. This
piece of code replaces those characters which are not considered readable by a 
replacement. The other characters are appended unchanged. If UTF-8 encoding is 
available (see the code snippets in the previous section on how to do this), the
version below will display much more characters. They may not all be readable, 
but they do look interesting. ;-)
	#include <string>
#include <sstream>
std::string make_readable(const std::string& inputData, 
    const std::string& replacement = ".")
{
    std::ostringstream buffer;
    unsigned char currentChar;
    for (unsigned int i = 0; i < inputData.size(); i++)
    {
        currentChar = static_cast<unsigned char>(inputData[i]);
        if (((currentChar >= 32) && (currentChar <= 126))
            || (currentChar >= 160))
            buffer << inputData[i];
        else
            buffer << replacement;
    }
    return buffer.str();
}
// This requires the uint_to_utf8() function from the previous section.
std::string make_readable(const std::string& inputData, 
    const std::string& replacement = ".")
{
    std::ostringstream buffer;
    unsigned int currentChar;
    for (unsigned int i = 0; i < inputData.size(); i++)
    {
        currentChar = static_cast<unsigned int>(
            static_cast<unsigned char>(inputData[i]));
        if ((currentChar >= 32) && (currentChar <= 126))
            buffer << inputData[i];
        else
        if (currentChar >= 127)
            buffer << uint_to_utf8(currentChar);
        else
            buffer << replacement;
    }
    return buffer.str();
}
	Make Nice Hexadecimal Output
	Now we are ready to do some really nice things with the hexadecimal string and 
the readable representation of the data. The following function creates a column
layout with arranges the bytes properly beside the readable characters. The 
version below fills in some defaults and puts everything together for a hex view
which is really simple to use at any time when data needs to be inspected 
closely.
	#include <string>
#include <sstream>
std::string make_nice_hex(const std::string& hex, const std::string& readable, 
    int bytesPerLine, int groupBytes)
{
    std::ostringstream buffer;
    std::string paddedHex(hex);
    std::string paddedReadable(readable);
    if ((paddedHex.size() % 2) != 0)
        paddedHex.append(" ");
    while (((paddedHex.size() / 2) % bytesPerLine) != 0)
        paddedHex.append("  ");
    unsigned int bytes = paddedHex.size() / 2;
    while (paddedReadable.size() < bytes)
        paddedReadable.append(" ");
    int readablePos = 0;
    for (unsigned int i = 0; i < bytes; i++)
    {
        buffer << paddedHex.substr(2 * i, 2) << " ";
        if ((((i + 1) % groupBytes) == 0) && (((i + 1) % bytesPerLine) != 0))
            buffer << " ";
        if (((i + 1) % bytesPerLine) == 0)
        {
            buffer << " " << paddedReadable.substr(readablePos, bytesPerLine) << "n";
            readablePos += bytesPerLine;
        }
    }
    return buffer.str();
}
std::string make_nice_hex(const std::string& data, int bytesPerLine = 20, 
    int groupBytes = 10)
{
    return make_nice_hex(make_hex(data), make_readable(data, "."), 
        bytesPerLine, groupBytes);
}