Monday, 26 May 2008

C: hex dump application

A C version of PrintHex to avoid a dependency on Mono.

Compilation, usage and output:
$ gcc phex.c -o phex
$ ./phex phex.h
23 69 6E 63 6C 75 64 65 20 3C 73 74 64 69 6F 2E         #include <stdio.
68 3E 0D 0A 0D 0A 76 6F 69 64 20 70 72 69 6E 74         h>____void print
46 69 6C 65 41 73 48 65 78 28 46 49 4C 45 2A 20         FileAsHex(FILE*
66 69 6C 65 29 3B 0D 0A 63 68 61 72 20 74 6F 56         file);__char toV
69 73 69 62 6C 65 43 68 61 72 61 63 74 65 72 28         isibleCharacter(
69 6E 74 20 62 79 74 65 56 61 6C 29 3B 0D 0A 76         int byteVal);__v
6F 69 64 20 77 72 69 74 65 4C 69 6E 65 28 69 6E         oid writeLine(in
74 20 63 6F 75 6E 74 2C 20 63 68 61 72 2A 20 6C         t count, char* l
69 6E 65 42 75 66 66 65 72 2C 20 69 6E 74 20 62         ineBuffer, int b
75 66 6C 65 6E 29 3B 0D 0A 63 68 61 72 20 75 70         uflen);__char up
70 65 72 54 6F 48 65 78 28 69 6E 74 20 62 79 74         perToHex(int byt
65 56 61 6C 29 3B 0D 0A 63 68 61 72 20 6C 6F 77         eVal);__char low
65 72 54 6F 48 65 78 28 69 6E 74 20 62 79 74 65         erToHex(int byte
56 61 6C 29 3B 0D 0A 63 68 61 72 20 6E 69 62 62         Val);__char nibb
6C 65 54 6F 48 65 78 28 69 6E 74 20 6E 69 62 62         leToHex(int nibb
6C 65 29 3B 0D 0A 0D 0A                                 le);____


Listing: const.h


//Win32 + *nix
#ifdef WIN32
    #define CRLF    "\r\n"
#else
    #define CRLF    "\n"
#endif

//number of bytes per line
#define LINELEN     16



Listing: phex.h

#include <stdio.h>

void printFileAsHex(FILE* file);
char toVisibleCharacter(int byteVal);
void writeLine(char* lineBuffer, int buflen);
char upperToHex(int byteVal);
char lowerToHex(int byteVal);
char nibbleToHex(int nibble);



Listing: phex.c

#include "phex.h"
#include "consts.h"

int main(int argc, const char* argv[])
{
    FILE* file;
    
    if(argc != 2)
    {
        printf("Usage: phex <file>");
        printf(CRLF);
        return 1;
    }
    
    file = fopen(argv[1], "rb");
    if(NULL == file)
    {
        printf("Cannot open %s", argv[1]);
        printf(CRLF);
        return 2;
    }
    
    printFileAsHex(file);
    
    fclose(file);
    
    return 0;
}

void printFileAsHex(FILE* file)
{
    int count = 0;
    char buffer[LINELEN];
    
    while(1)
    {
        int byteVal = fgetc(file);
        
        if(EOF == byteVal)
        {
            break;
        }

        buffer[count] = byteVal;
        count++;
        if(count >= LINELEN)
        {
            writeLine(buffer, LINELEN);
            count = 0;
        }
    }

    if(count > 0)
    {
        writeLine(buffer, count);
    }
}

char toVisibleCharacter(int byteVal)
{
    if(byteVal >= 32 && byteVal <= 126)
    {
        return (char) byteVal;
    }
    
    return '_';
}

void writeLine(char* lineBuffer, int buflen)
{
    int i;

    for(i=0; i<buflen; i++)
    {
        char chu = upperToHex(lineBuffer[i]);
        char chl = lowerToHex(lineBuffer[i]);
        printf("%c%c ", chu, chl);
    }
    
    if(buflen < LINELEN)
    {
        for(i = LINELEN - buflen; i>0; i--)
        {
            printf("   ");
        }
    }

    printf("\t");
    
    for(i=0; i<buflen; i++)
    {
        char ch = toVisibleCharacter(lineBuffer[i]);
        printf("%c", ch);
    }

    printf(CRLF);
}

char upperToHex(int byteVal)
{
    int i = (byteVal & 0xF0) >> 4;
    return nibbleToHex(i);
}

char lowerToHex(int byteVal)
{
    int i = (byteVal & 0x0F);
    return nibbleToHex(i);
}

char nibbleToHex(int nibble)
{
    const int ascii_zero = 48;
    const int ascii_a = 65;
    
    if((nibble >= 0) && (nibble <= 9))
    {
        return (char) (nibble + ascii_zero);
    }
    if((nibble >= 10) && (nibble <= 15))
    {
        return (char) (nibble - 10 + ascii_a);
    }
    return '?';
}

Sample Code in Subversion

A faster version with input buffering is available from source control.

Repository: http://illegalargumentexception.googlecode.com/svn/trunk/code/c/
License: MIT
Project: phex

2 comments:

  1. Seen xxd? Try man xxd on Linux

    ReplyDelete
  2. Thanks. xxd is orders of magnitude better than my app - I just like mucking about with code and much of what gets posted here is the random result of that.

    ReplyDelete

All comments are moderated