/* ------  functions open for use:  (i.e. non-static) ------------------ 
 *
 * r_sprintf_long_to_hex  - convert a long to a hex digit string
 *
 * r_hex_str_to_long      - convert a hex digit string to a long
 *
 * ---------------------------------------------------------------------
*/


#include <stdio.h>
#include "r_misc.h"

/* -- locals */
static int ulong_size ( unsigned long l );
/* -- end locals */


/*----------------------------------------------------------------------
 * r_hex_str_to_long    - convert hex_digits hex digits to a long
 *
 * Conver up to 8 hex digits into a single unsigned long integer.
 * The input string must consist of hex type characters, without
 * a leading 0x.  i.e. '0'->'9', 'a'->'f' and 'A'->'F'.
 *
 * return the unsigned long integer, or 0 on failure
 *----------------------------------------------------------------------
*/
unsigned long
r_hex_str_to_long ( char * src, int hex_digits )
{
    unsigned long   res = 0;
    char          * cp;
    int             nib, digs;

    if ( hex_digits <= 0 || hex_digits > 8 )
        return 0;

    for ( digs = hex_digits, cp = src; digs > 0; digs--, cp++ )
    {
        if ( (*cp >= '0') && (*cp <= '9') )
            nib = *cp - '0';
        else if ( (*cp >= 'a') && (*cp <= 'f') )
            nib = *cp - 'a' + 10;
        else if ( (*cp >= 'A') && (*cp <= 'F') )
            nib = *cp - 'A' + 10;
        else
        {
            fprintf( stderr, "r_hex_str_to_long: invalid input string <%8s>\n",
                     src );
            return 0;
        }

        res = (res << 4) + (nib & 0xf);
    }

    return res;
}


/*----------------------------------------------------------------------
 * r_sprintf_long_to_hex    - write hex chars to a string
 *
 * Convert the low-order number of bytes from the unsigned long into
 * a null-terminated string hex characters (strlen() is twice the
 * number of converted bytes).
 *
 * We input the option to pad the string with zeros if the number
 * is too small for the requested number of bytes.
 *
 * return number of hex pairs written (if padding, should equal bytes)
 *----------------------------------------------------------------------
*/
int
r_sprintf_long_to_hex
    (
        char          * dest,           /* location of output string     */
        unsigned long   lsrc,           /* number to translate           */
        int             bytes,          /* total bytes (hex pairs)       */
        int             pad             /* pad the result with zeros?    */
    )
{
    static char hexstring[] = "0123456789ABCDEF";

    unsigned char   ub;
    char          * cp = dest;
    int             posn, size, ret;

    if ( (bytes <= 0) || (bytes > 4) )
    {
        *cp = '\0';
        return 0;
    }

    size = ulong_size( lsrc );

    if ( (size < bytes) && !pad )       /* use size if we avoid padding  */
        ret = size;
    else
        ret = bytes;

    for ( posn = ret-1; posn >= 0; posn-- )
    {
        /* write one hex pair for this byte */
        ub = ( lsrc >> (posn << 3) ) & 0xff;            /* current ubyte */
        *cp++ = hexstring[(ub>>4) & 0xf];               /* upper nibble  */
        *cp++ = hexstring[ ub     & 0xf];               /* lower nibble  */
    }

    *cp = '\0';

    return ret;
}

/* return number of bytes needed to represent a long - return at least 1 */
static int
ulong_size ( unsigned long l )
{
    if ( l & 0xff000000 )
        return 4;

    if ( l & 0xff0000 )
        return 3;

    if ( l & 0xff00 )
        return 2;

    return 1;
}



syntax highlighted by Code2HTML, v. 0.9.1