#include  "stdafx.h"
#include  "cstrutil.h"
#include  "gcommlib.h"
#include  "string.h"
#include  "CnfAsrt.h"

#define FILREV "$Revision: $"

inline unsigned char hexVal( char ch )
{
     char      lch = tolower( ch );

     CnfAssert( isxdigit( lch ) );

     unsigned char res = isdigit( lch ) ? (lch - '0') : ((lch - 'a') + 10);

     return( res );
}


void lTrim( CString &st )
{
     int       len = st.GetLength();
     int       firstNonSpace = len;

     for ( int count = 0; count < len; ++count )
     {
          if (! isspace( st[ count ] ))
          {
               firstNonSpace = count;
               break;
          }
     }

     if (firstNonSpace != 0)
          st = st.Mid( firstNonSpace );

     return;
}


void rTrim( CString &st )
{
     int       lastNonSpace = -1;
     int       len = st.GetLength();

     for ( int count = len - 1; count >= 0; --count )
     {
          if (! isspace( st[ count ] ))
          {
               lastNonSpace = count;
               break;
          }
     }

     if ((lastNonSpace + 1) != len)
          st = st.Left( lastNonSpace + 1 );

     return;
}


void lrTrim( CString &st )
{
     lTrim( st );
     rTrim( st );

     return;
}


BOOL IsNumber( const CString &st )
{
     const char *cp = st;

     if (*cp == '-')
     {
          ++cp;
     }

     return( (strlen( st ) > 0) && alldgs( cp ) );
}


BOOL IsHexNumber( const CString &st )
{
     return( (st.GetLength() > 0) && allhex( st ) );
}


LONG htol( const CString &st )
{
     CnfAssert( IsHexNumber( st ) );

     LONG      result = 0;

     for ( int count = 0; count < st.GetLength(); ++count )
     {
          result <<= 4;
          result += hexVal( st[ count ] );
     }

     return( result );
}


//   brain-dead temporary implementation
//
int SearchNoCase( const CString &fullText, const CString &target )
{
     char      firstCh = tolower( target[ 0 ] );
     int       result = -1;

     int       targLen = target.GetLength();
     int       maxPos = fullText.GetLength() - targLen;

     for ( int pos = 0; pos <= maxPos; ++pos )
     {
          if (tolower( fullText[ pos ] ) == firstCh)
          {
               if (_memicmp( ((const char *)fullText) + pos, target, targLen ) == 0)
               {
                    result = pos;
                    break;
               }
          }
     }

     return( result );
}


//   DEBUG

//   Boyer-Moore-Gosper string search stuff
//

static int searchTable[ (unsigned int)UCHAR_MAX + 1 ]; // BMG skip table
static CString bmgText;            // text we're searching for                
static unsigned char bmgLast;      // last char of bmgText                    
static int bmgLen;                 // length of bmgText                       
static const char *bmgSt;          // char ptr to bmgText                     

void 
BmgInit(                           // setup a new search string
const CString &searchText)         //   string we'll search for
{
     int       tlen = searchText.GetLength();

     CnfAssert( tlen > 0 );

     for ( int count = 0; count <= UCHAR_MAX; ++count )
     {
          searchTable[ count ] = tlen;
     }

     for ( int pos = 0; pos < (tlen - 1); ++pos )
     {
          unsigned char ch = static_cast< unsigned char >( searchText[ pos ] );
          unsigned char lowChar;
          unsigned char upChar;

          if (islower( ch ))
          {
               lowChar = ch;
               upChar = toupper( ch );
          }
          else if (isupper( ch ))
          {
               upChar = ch;
               lowChar = tolower( ch );
          }
          else
          { 
               upChar = lowChar = ch;
          }

          searchTable[ upChar ] = searchTable[ lowChar ] = (tlen - 1) - pos;
     }

     bmgText = searchText;
     bmgSt = (const char *)bmgText;

     if (tlen > 0)
     {
          bmgLast = static_cast< unsigned char >( bmgText[ tlen - 1 ] );
          bmgLast = tolower( bmgLast );
     }
     else
     {
          bmgLast = 0;
     }          

     bmgLen = tlen;

     return;
}


BOOL                               //   TRUE if search string was found
BmgSearch(                         // search a string for our target
const CString &text)               //   string to search in
{
     CnfAssert( bmgLen > 0 );
     CnfAssert( bmgLen == bmgText.GetLength() );
     CnfAssert( bmgLast = tolower( bmgText[ bmgLen - 1 ] ) );
     CnfAssert( bmgSt != NULL );
     CnfAssert( bmgText.Compare( bmgSt ) == 0 );

     BOOL      found = FALSE;

     int       lastPos = bmgLen - 1;
     int       tlen = text.GetLength();

     const char *st = (const char *)text;

     while (lastPos < tlen)
     {
          if ((tolower( st[ lastPos ] ) == bmgLast) &&
              (_memicmp( st + lastPos - bmgLen + 1, bmgSt, bmgLen ) == 0)
             )
          {
               found = TRUE;
               break;
          }
          else
          {
               lastPos += searchTable[ st[ lastPos ] ];
          }
     }

     return( found );
}

