WvStreams
wvhex.cc
00001 /*
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
00004  *
00005  * Hex encoder and decoder.
00006  */
00007 #include "wvhex.h"
00008 #include <ctype.h>
00009 
00010 
00011 static inline char tohex(int digit, char alphabase)
00012 {
00013     return (digit < 10 ? '0' : alphabase) + digit;
00014 }
00015 
00016 static inline int fromhex(char digit)
00017 {
00018     if (isdigit(digit))
00019         return digit - '0';
00020     if (isupper(digit))
00021         return digit - 'A' + 10;
00022     return digit - 'a' + 10;
00023 }
00024 
00025 /***** WvHexEncoder *****/
00026 
00027 WvHexEncoder::WvHexEncoder(bool use_uppercase) 
00028 {
00029     alphabase = (use_uppercase ? 'A' : 'a') - 10;
00030     _reset();
00031 }
00032 
00033 
00034 bool WvHexEncoder::_reset()
00035 {
00036     return true;
00037 }
00038 
00039 
00040 bool WvHexEncoder::_encode(WvBuf &in, WvBuf &out, bool flush)
00041 {
00042     while (in.used() != 0)
00043     {
00044         unsigned char byte = in.getch();
00045         out.putch(tohex(byte >> 4, alphabase));
00046         out.putch(tohex(byte & 15, alphabase));
00047     }
00048     return true;
00049 }
00050 
00051 
00052 /***** WvHexDecoder *****/
00053 
00054 WvHexDecoder::WvHexDecoder()
00055 {
00056     _reset();
00057 }
00058 
00059 
00060 bool WvHexDecoder::_reset()
00061 {
00062     issecond = false;
00063     first = 0;
00064     return true;
00065 }
00066 
00067 
00068 bool WvHexDecoder::_encode(WvBuf &in, WvBuf &out, bool flush)
00069 {
00070     while (in.used() != 0)
00071     {
00072         char ch = (char) in.getch();
00073         if (isxdigit(ch))
00074         {
00075             int digit = fromhex(ch);
00076             if ( (issecond = ! issecond) )
00077                 first = digit;
00078             else
00079                 out.putch(first << 4 | digit);
00080             continue;
00081         }
00082         if (isspace(ch))
00083             continue;
00084         seterror("invalid character '%s' in hex input", ch);
00085         return false;
00086     }
00087     if (flush && issecond)
00088         return false; // not enough hex digits supplied
00089     return true;
00090 }
00091 
00092 
00093 /*** Compatibility ***/
00094 
00095 void hexify(char *obuf, const void *ibuf, size_t len)
00096 {
00097     size_t outlen = len * 2 + 1;
00098     WvHexEncoder(false /*use_uppercase*/).
00099         flushmemmem(ibuf, len, obuf, & outlen);
00100     obuf[outlen] = '\0';
00101 }
00102 
00103 
00104 void unhexify(void *obuf, const char *ibuf)
00105 {
00106     size_t inlen = strlen(ibuf);
00107     size_t outlen = inlen / 2;
00108     WvHexDecoder().flushmemmem(ibuf, inlen, obuf, & outlen);
00109 }