229 lines
5.3 KiB
C++
229 lines
5.3 KiB
C++
/* -----------------------------------------------------------------------------
|
|
GSFramework
|
|
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
|
|
#include "ascii/ascii_encoder.h"
|
|
#include "log/log.h"
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
#define FEED_OUT(out_c) \
|
|
{ \
|
|
if (out) \
|
|
{ \
|
|
if (olen < max) \
|
|
out[olen] = (uchar)(out_c); \
|
|
else \
|
|
break; \
|
|
} \
|
|
olen++; \
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
//---------------------------------------------------------------------------
|
|
#define FEED_IN(in_v) \
|
|
{ \
|
|
if (!len) \
|
|
{ \
|
|
__LOG_W__ << "input buffer underflow.\n"; \
|
|
break; \
|
|
} \
|
|
(in_v) = (int)*in++; \
|
|
len--; \
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
/*
|
|
|
|
From UUencode wikipedia.
|
|
------------------------
|
|
|
|
(...)
|
|
Uuencode repeatedly takes in a group of three bytes, adding trailing zeros
|
|
if there are less than three bytes left. These 24 bits are split into four
|
|
groups of six which are treated as numbers between 0 and 63.
|
|
Decimal 32 is added to each number and they are ouput as ASCII characters
|
|
which will lie in the range 32 (space) to 32+63 = 95 (underscore).
|
|
ASCII characters greater than 95 may also be used; however, only the six
|
|
right-most bits are relevant.
|
|
Each group of sixty output characters (corresponding to 45 input bytes) is
|
|
output as a separate line preceded by an 'M' (ASCII code 77 = 32+45).
|
|
At the end of the input, if there are N output characters left after the
|
|
last group of sixty and N>0 then they will be preceded by the character
|
|
whose code is 32+N.
|
|
(...)
|
|
|
|
*/
|
|
|
|
//-----------------------------------------------------------------------------
|
|
uint nAsciiEncoder::UUEncode(const uchar *in, size_t len, uchar *out, size_t max)
|
|
{
|
|
uint olen = 0, n;
|
|
|
|
while (len)
|
|
{
|
|
uchar *p = out ? &out[olen] : NULL;
|
|
FEED_OUT(0) // Dummy feed.
|
|
|
|
for (n = 0; (n < 15) && len; n++)
|
|
{
|
|
uchar a, b, c;
|
|
a = *in++;
|
|
len--;
|
|
if (len) { len--; b = *in++; } else b = 0;
|
|
if (len) { len--; c = *in++; } else c = 0;
|
|
|
|
uint f = (a << 16) + (b << 8) + c;
|
|
uchar w, x, y, z;
|
|
|
|
z = (f & 63) + 32;
|
|
y = ((f >> 6) & 63) + 32;
|
|
x = ((f >> 12) & 63) + 32;
|
|
w = ((f >> 18) & 63) + 32;
|
|
|
|
FEED_OUT(w);
|
|
FEED_OUT(x);
|
|
FEED_OUT(y);
|
|
FEED_OUT(z);
|
|
}
|
|
if (p)
|
|
p[0] = (uchar)(n * 3 + 32);
|
|
FEED_OUT('\n')
|
|
}
|
|
return olen;
|
|
}
|
|
uint nAsciiEncoder::UUDecode(const uchar *in, size_t len, uchar *out, size_t max)
|
|
{
|
|
uint olen = 0, n;
|
|
|
|
while (len)
|
|
{
|
|
uint lsize;
|
|
FEED_IN(lsize);
|
|
lsize = (lsize - 32) / 3;
|
|
|
|
if (len)
|
|
for (n = 0; n < lsize; n++)
|
|
{
|
|
int x, y, z, w;
|
|
FEED_IN(w); w -= 32;
|
|
FEED_IN(x); x -= 32;
|
|
FEED_IN(y); y -= 32;
|
|
FEED_IN(z); z -= 32;
|
|
|
|
uchar a, b, c;
|
|
int f = (w << 18) + (x << 12) + (y << 6) + z;
|
|
a = (f >> 16) & 255;
|
|
b = (f >> 8) & 255;
|
|
c = f & 255;
|
|
|
|
FEED_OUT(a);
|
|
FEED_OUT(b);
|
|
FEED_OUT(c);
|
|
}
|
|
|
|
if (len)
|
|
FEED_IN(n); // Line jump.
|
|
}
|
|
return olen;
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
|
|
/*
|
|
|
|
From yEnc.org (revision 1.3)
|
|
----------------------------
|
|
|
|
A typical encoding process might look something like this:
|
|
|
|
1. Fetch a character from the input stream.
|
|
2. Increment the character's ASCII value by 42, modulo 256
|
|
3. If the result is a critical character (as defined in the previous
|
|
section), write the escape character to the output stream and increment
|
|
character's ASCII value by 64, modulo 256.
|
|
4. Output the character to the output stream.
|
|
5. Repeat from start.
|
|
|
|
(...)
|
|
Under special circumstances, a single escape character (ASCII 3Dh, "=") is
|
|
used to indicate that the following output character is "critical", and
|
|
requires special handling.
|
|
|
|
Critical characters include the following:
|
|
|
|
ASCII 00h (NULL)
|
|
ASCII 0Ah (LF)
|
|
ASCII 0Dh (CR)
|
|
ASCII 3Dh (=)
|
|
|
|
> ASCII 09h (TAB) -- removed in version (1.2)
|
|
|
|
*/
|
|
|
|
//-----------------------------------------------------------------------------
|
|
uint nAsciiEncoder::yEncode(const uchar *in, size_t len, uchar *out, size_t max, uint line_length)
|
|
{
|
|
if (line_length <= 0)
|
|
__ERR__(__LOG_E__ << "invalid line-feed size for yEncoding.\n", 0)
|
|
|
|
uint olen = 0;
|
|
int cchr = (int)line_length;
|
|
|
|
while (len--)
|
|
{
|
|
// Line-feed.
|
|
if (cchr <= 0)
|
|
{
|
|
FEED_OUT('\n')
|
|
cchr = (int)line_length;
|
|
}
|
|
|
|
// yEnc.
|
|
int v = (int(*in++) + 42) % 256;
|
|
|
|
switch (v)
|
|
{
|
|
case 0x00:
|
|
case 0x0a:
|
|
case 0x0d:
|
|
case 0x3d:
|
|
FEED_OUT(0x3d)
|
|
cchr--;
|
|
v = (v + 64) % 256;
|
|
break;
|
|
}
|
|
|
|
FEED_OUT(v)
|
|
cchr--;
|
|
}
|
|
return olen;
|
|
}
|
|
uint nAsciiEncoder::yDecode(const uchar *in, size_t len, uchar *out, size_t max)
|
|
{
|
|
uint olen = 0;
|
|
while (len--)
|
|
{
|
|
int v = (int)*in++;
|
|
|
|
if (v == 0x0a)
|
|
FEED_IN(v)
|
|
if ((v == 0x0d) && (in[0] == 0x0a)) // [EJ support for Windows-style EOL]
|
|
{
|
|
++in;
|
|
len--;
|
|
FEED_IN(v)
|
|
}
|
|
|
|
if (v == 0x3d)
|
|
{
|
|
FEED_IN(v)
|
|
v = (v - 64) % 256;
|
|
}
|
|
FEED_OUT((v - 42) % 256)
|
|
}
|
|
return olen;
|
|
}
|
|
//-----------------------------------------------------------------------------
|