/*
 * Xailer source code:
 *
 * Control.prg
 * Funciones StrEncode32() y StrDecode32()
 *
 * Copyright 2007 Jose F. Gimenez
 * Copyright 2007 Xailer.com
 * All rights reserved
 *
 */

#include "Xailer.h"

static char chars32[] = "0123456789ACDEFGHIJKLMPRSTUVWXYZ";

//------------------------------------------------------------------------------

char * StrEncode32( const char *cIn, int nLen )
{
   unsigned char *cOut, *pOut, *cString;

   if( nLen == 0 )
      nLen = strlen( cIn );

   cString = (unsigned char *) cIn;
   if( nLen )
      {
      cOut = hb_xgrab( ( ( nLen * 8 ) / 5 ) + 9 );
      pOut = cOut;
      while( nLen > 0 )
         {
         *pOut++ = chars32[ *cString >> 3 ];
         if( nLen-- > 0 )
            *pOut++ = chars32[ ( ( *cString & 0x07 ) << 2 ) | ( cString[1] >> 6 ) ];
         if( nLen > 0 )
            *pOut++ = chars32[ ( ( cString[1] & 0x3f ) >> 1 ) ];
         if( nLen-- > 0 )
            *pOut++ = chars32[ ( ( cString[1] & 0x01 ) << 4 ) | ( cString[2] >> 4 ) ];
         if( nLen-- > 0 )
            *pOut++ = chars32[ ( ( cString[2] & 0x0f ) << 1 ) | ( cString[3] >> 7 ) ];
         if( nLen > 0 )
            *pOut++ = chars32[ ( ( cString[3] & 0x7f ) >> 2 ) ];
         if( nLen-- > 0 )
            *pOut++ = chars32[ ( ( cString[3] & 0x03 ) << 3 ) | ( cString[4] >> 5 ) ];
         if( nLen-- > 0 )
            *pOut++ = chars32[ cString[4] & 0x1f ];
         cString += 5;
         }
      *pOut = 0;
      return( (char *) cOut );
      }
   else
      return( NULL );
}

//------------------------------------------------------------------------------

char * StrDecode32( const char *cString, int *nLen )
{
   unsigned char *cOut, *pOut, c;
   int nStrLen, n = 0;
   int nLen2;

   if( nLen == NULL )
      nLen = &nLen2;

   if( cString && *cString )
      {
      nStrLen = strlen( cString );
      *nLen = ( nStrLen * 5 + 7 ) >> 3;
      cOut = hb_xgrab( *nLen + 1 );
      pOut = cOut;
      memset( cOut, 0, *nLen + 1 );
      while( n <= nStrLen )
         {
         c = *cString++ - '0';
         if( c > 9 )
            {
            c -= '@'-'9';
            if( c > 10 )
               {
               c--;
               if( c > 21 )
                  {
                  c--;
                  c--;
                  if( c > 22 )
                     c--;
                  }
               }
            }
         switch( n & 7 )
            {
            case 0: *pOut = ( c << 3 ); break;
            case 1: *pOut++ |= ( c >> 2 ); *pOut = ( c << 6 ); break;
            case 2: *pOut |= ( c << 1 ); break;
            case 3: *pOut++ |= ( c >> 4 ); *pOut = ( c << 4 ); break;
            case 4: *pOut++ |= ( c >> 1 ); *pOut = ( c << 7 ); break;
            case 5: *pOut |= ( c << 2 ); break;
            case 6: *pOut++ |= ( c >> 3 ); *pOut = ( c << 5 ); break;
            case 7: *pOut++ |= c;
            }
         n++;
         }
      return( (char *) cOut );
      }
   else
      {
      *nLen = 0;
      return( NULL );
      }
}

//------------------------------------------------------------------------------

XA_FUNC( STRENCODE32 )
{
   char *cString = StrEncode32( hb_parc( 1 ), hb_parclen( 1 ) );

   if( cString )
      hb_retc_buffer( cString );
   else
      hb_retc( "" );
}

//------------------------------------------------------------------------------

XA_FUNC( STRDECODE32 )
{
   int nLen;
   char *cString = StrDecode32( hb_parc( 1 ), &nLen );

   if( cString )
      hb_retclen_buffer( cString, nLen );
   else
      hb_retc( "" );
}

//------------------------------------------------------------------------------
