#include "Encoder.h"
#include <ctype.h>
#include <stdio.h>

const char Encoder::HEX[] = "0123456789abcdef";

size_t Encoder::UrlEncode( char const *src, size_t srclength, char *target,
                           size_t targsize )
{
    const char* pstr = src;
    char* pbuf = target;
    while( ( size_t )( pstr - src ) < srclength
            && ( size_t )( pbuf - target ) < targsize - 3 )
    {
        if( isalnum( *pstr ) || *pstr == '-' || *pstr == '_' || *pstr == '.'
                || *pstr == '~' )
        {
            *pbuf++ = *pstr;
        }
        else if( *pstr == ' ' )
        {
            *pbuf++ = '+';
        }
        else
        {
            *pbuf++ = '%';
            *pbuf++ = HEX[( *pstr >> 4 ) & 0xF ];
            *pbuf++ = HEX[*pstr & 0xF];
        }
        pstr++;
    }
    *pbuf = '\0';
    return ( size_t )( pbuf - target );
}

/* Converts a hex character to its integer value */
char from_hex( char ch )
{
    return isdigit( ch ) ? ch - '0' : tolower( ch ) - 'a' + 10;
}

size_t Encoder::UrlDecode( char const *src, char *target, size_t targsize )
{
    const char* pstr = src;
    char* pbuf = target;
    while( *pstr && ( size_t )( pbuf - target ) < targsize )
    {
        if( *pstr == '%' )
        {
            if( pstr[1] && pstr[2] )
            {
                *pbuf++ = from_hex( pstr[1] ) << 4 | from_hex( pstr[2] );
                pstr += 2;
            }
        }
        else if( *pstr == '+' )
        {
            *pbuf++ = ' ';
        }
        else
        {
            *pbuf++ = *pstr;
        }
        pstr++;
    }
    *pbuf = '\0';
    return ( size_t )( pbuf - target );
}

