So who would have thought that Hexadecimal to ASCII encoding methods would turn into an entire series. So here is the fourth (I think) installment of ever-so-illusive algorithm from A. C. Hynes, implemented yet again in C:

typedef enum {
    H2AERR_OK,
    H2AERR_BUFFER_TOO_SMALL,
    H2AERR_INVALID_HEX,
} h2a_err_t;
h2a_err_t hex2asc( char * to, const char * from, size_t size )
{
    int c = 0;
    h2a_err_t rtn = H2AERR_OK;
    if ( ! size )
        return H2AERR_BUFFER_TOO_SMALL;
H2A_START:
    if ( ! --size ) {
        rtn = H2AERR_BUFFER_TOO_SMALL;
        goto H2A_ACCEPT;
    }
    c = *from++;
    switch ( c ) {
        case 0:
            goto H2A_ACCEPT;
        case '%':
            goto H2A_PCNT_0;
        default:
            *to++ = c;
            goto H2A_START;
    }
H2A_PCNT_0:
    if ( ! --size ) {
        rtn = H2AERR_BUFFER_TOO_SMALL;
        goto H2A_ACCEPT;
    }
    c = *from++;
    if ( isxdigit( c ) )
        goto H2A_PCNT_1;
    rtn = H2AERR_INVALID_HEX;
    goto H2A_ACCEPT;
H2A_PCNT_1:
    if ( ! --size ) {
        rtn = H2AERR_BUFFER_TOO_SMALL;
        goto H2A_ACCEPT;
    }
    c = *from++;
    if ( isxdigit( c ) ) {
        *to++ = strtol( from - 2, NULL, 16 );
        goto H2A_START;
    }
    rtn = H2AERR_INVALID_HEX;
    goto H2A_ACCEPT;
H2A_ACCEPT:
    *to = 0;
    return rtn;
}