#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "ftpmunge.h"
typedef enum ConversionState {
kNormal = 0x01, kCaret = 0x02, kStartZero = 0x04, kStartTwo = 0x08, kStartFive = 0x10 } ConversionState;
size_t ftp2rawstrlen( const char *ftp );
size_t ftp2rawstrlen( const char *ftp )
{
size_t len = 0;
ConversionState state = kNormal;
for( const char *s = ftp; s && *s; s++ ) {
if( kCaret == state && '0' == *s ) {
state = kStartZero;
continue;
}
else if( kCaret == state && '2' == *s ) {
state = kStartTwo;
continue;
}
else if( kCaret == state && '5' == *s ) {
state = kStartFive;
continue;
}
else if( kCaret == state ) len += 2;
else if( kStartZero == state && '9' == *s ) len++;
else if( kStartZero == state && ('A' == *s || 'a' == *s) ) len++;
else if( kStartZero == state ) len += 3;
else if( kStartTwo == state && '0' == *s ) len++;
else if( kStartTwo == state ) len += 3;
else if( kStartFive == state && ('E' == *s || 'e' == *s) ) len++;
else if( kStartFive == state ) len += 3;
else if( '^' == *s ) {
state = kCaret;
continue;
}
else len++;
state = kNormal;
}
if( kCaret == state ) len += 1;
else if( kNormal != state ) len += 2;
return len;
}
char *ftp2rawstr( const char *ftp ) throw( std::bad_alloc )
{
if( !ftp )
return NULL;
char *raw = new char[ ftp2rawstrlen( ftp ) + 1 ];
char *raw_start = raw;
ConversionState state = kNormal;
for( ; ftp && *ftp; ftp++ ) {
retry:
if( kCaret == state && '0' == *ftp ) {
state = kStartZero;
continue;
}
else if( kCaret == state && '2' == *ftp ) {
state = kStartTwo;
continue;
}
else if( kCaret == state && '5' == *ftp ) {
state = kStartFive;
continue;
}
else if( kCaret == state ) { *raw = '^'; raw++;
state = kNormal;
goto retry;
}
else if( kStartZero == state && '9' == *ftp ) *raw = '\t';
else if( kStartZero == state && ('A' == *ftp || 'a' == *ftp))
*raw = '\n';
else if( kStartZero == state ) { *raw = '^'; raw++;
*raw = '0'; raw++;
state = kNormal;
goto retry;
}
else if( kStartTwo == state && '0' == *ftp ) *raw = ' ';
else if( kStartTwo == state ) { *raw = '^'; raw++;
*raw = '2'; raw++;
state = kNormal;
goto retry;
}
else if( kStartFive == state && ('E' == *ftp || 'e' == *ftp) )
*raw = '^';
else if( kStartFive == state ) { *raw = '^'; raw++;
*raw = '5'; raw++;
state = kNormal;
goto retry;
}
else if( '^' == *ftp ) {
state = kCaret;
continue;
}
else *raw = *ftp;
state = kNormal;
raw++;
}
if( kCaret == state ) { *raw = '^'; raw++;
}
else if( kStartZero == state ) { *raw = '^'; raw++;
*raw = '0'; raw++;
}
else if( kStartTwo == state ) { *raw = '^'; raw++;
*raw = '2'; raw++;
}
else if( kStartFive == state ) { *raw = '^'; raw++;
*raw = '5'; raw++;
}
*raw = '\0';
return raw_start;
}
char *raw2ftpstr( const char *raw ) throw( std::bad_alloc )
{
if( !raw )
return NULL;
int len = 0;
for( const char *s = raw; s && *s; s++ ) {
switch( *s ) {
case ' ':
case '\t':
case '^':
len += 3;
break;
default:
len++;
break;
}
}
len++; char *ftp = new char[ len ];
char *ftp_start = ftp;
if( !ftp )
return NULL;
for( ; raw && *raw; raw++, ftp++ ) {
switch( *raw ) {
case ' ':
*ftp = '^'; ftp++;
*ftp = '2'; ftp++;
*ftp = '0';
break;
case '\t':
*ftp = '^'; ftp++;
*ftp = '0'; ftp++;
*ftp = '9';
break;
case '^':
*ftp = '^'; ftp++;
*ftp = '5'; ftp++;
*ftp = 'E';
break;
case '\n':
*ftp = '^'; ftp++;
*ftp = '0'; ftp++;
*ftp = 'A'; ftp++;
break;
default:
*ftp = *raw;
break;
}
}
*ftp = '\0';
return ftp_start;
}