151 lines
5.2 KiB
C#
151 lines
5.2 KiB
C#
using System;
|
|
using System.Text;
|
|
|
|
namespace skyscraper5.Skyscraper.Text
|
|
{
|
|
abstract class SkyscraperBaseEncoding8 : Encoding
|
|
{
|
|
protected abstract char[] Decrypt(byte[] preprocessed);
|
|
|
|
private char[] lastDecrypted;
|
|
private byte[] lastBuffer;
|
|
private bool IsSameStringAsLast(byte[] buffer, int index, int count)
|
|
{
|
|
if (lastBuffer == null)
|
|
{
|
|
//Dies ist der erste call.
|
|
lastBuffer = new byte[count];
|
|
Array.Copy(buffer, index, lastBuffer, 0, count);
|
|
return false;
|
|
}
|
|
|
|
if (lastBuffer.Length != count)
|
|
{
|
|
//string länge anders als beim letzten mal, kann also nicht der selbe sein.
|
|
lastBuffer = new byte[count];
|
|
Array.Copy(buffer, index, lastBuffer, 0, count);
|
|
return false;
|
|
}
|
|
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
if (lastBuffer[i] != buffer[i + index])
|
|
{
|
|
//String anders als beim letzen mal
|
|
lastBuffer = new byte[count];
|
|
Array.Copy(buffer, index, lastBuffer, 0, count);
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
protected virtual int GetPreProcessLength(byte[] buffer, int index, int count)
|
|
{
|
|
int result = 0;
|
|
byte t;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
t = buffer[i + index];
|
|
if (t >= 0x80 && t <= 0x85)
|
|
continue; //reserved for future use
|
|
if (t == 0x86)
|
|
continue; //character emphasis on
|
|
if (t == 0x87)
|
|
continue; //character emphasis off
|
|
if (t >= 0x88 && t <= 0x89)
|
|
continue; //reserved for future use
|
|
if (t == 0x8a)
|
|
result += 2; //CRLF
|
|
if (t >= 0x8b && t <= 0x9f)
|
|
continue; //user defined
|
|
result++;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
protected virtual byte[] PreProcess(byte[] buffer, int index, int count, int predictedLength)
|
|
{
|
|
byte[] result = new byte[predictedLength];
|
|
int outputOffset = 0;
|
|
byte t;
|
|
for (int inputOffset = 0; inputOffset < count; inputOffset++)
|
|
{
|
|
t = buffer[inputOffset + index];
|
|
if (t >= 0x80 && t <= 0x85)
|
|
continue; //reserved for future use
|
|
if (t == 0x86)
|
|
continue; //character emphasis on
|
|
if (t == 0x87)
|
|
continue; //character emphasis off
|
|
if (t >= 0x88 && t <= 0x89)
|
|
continue; //reserved for future use
|
|
if (t == 0x8a)
|
|
{
|
|
result[outputOffset++] = 0x10;
|
|
result[outputOffset++] = 0x13;
|
|
continue;
|
|
}
|
|
|
|
if (t >= 0x8b && t <= 0x9f)
|
|
continue; //user defined
|
|
|
|
result[outputOffset++] = t;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public override int GetByteCount(char[] chars, int index, int count)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public override int GetCharCount(byte[] bytes, int index, int count)
|
|
{
|
|
if (!IsSameStringAsLast(bytes, index, count))
|
|
{
|
|
int preProcessLength = GetPreProcessLength(bytes, index, count);
|
|
byte[] preProcess = PreProcess(bytes, index, count, preProcessLength);
|
|
lastDecrypted = Decrypt(preProcess);
|
|
}
|
|
return lastDecrypted.Length;
|
|
}
|
|
|
|
public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
|
|
{
|
|
if (!IsSameStringAsLast(bytes, byteIndex, byteCount))
|
|
{
|
|
int preProcessLength = GetPreProcessLength(bytes, byteIndex, byteCount);
|
|
byte[] preProcess = PreProcess(bytes, byteIndex, byteCount, preProcessLength);
|
|
int maxAllowedSize = lastDecrypted.Length;
|
|
char[] overwriting = Decrypt(preProcess);
|
|
if (overwriting.Length > maxAllowedSize)
|
|
{
|
|
throw new AccessViolationException("Oh no, I guess the multithreading went haywire...");
|
|
}
|
|
lastDecrypted = overwriting;
|
|
}
|
|
|
|
int result = Math.Min(chars.Length - charIndex, lastDecrypted.Length);
|
|
Array.Copy(lastDecrypted, 0, chars, charIndex, result);
|
|
return result;
|
|
}
|
|
|
|
public override int GetMaxByteCount(int charCount)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public override int GetMaxCharCount(int byteCount)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
}
|