1
0
mirror of https://github.com/livingcomputermuseum/IFS.git synced 2026-01-29 21:30:54 +00:00
Files
livingcomputermuseum.IFS/PUP/BCPLString.cs

130 lines
3.9 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IFS
{
/// <summary>
/// A BCPL string is one byte of length N followed by N bytes of ASCII.
/// This class is a (very) simple encapsulation of that over a byte array.
/// </summary>
public class BCPLString
{
public BCPLString(string s)
{
if (s.Length > 255)
{
throw new InvalidOperationException("Max length for a BCPL string is 255 characters.");
}
_string = new byte[s.Length];
// We simply take the low 8-bits of each Unicode character and stuff it into the
// byte array. This works fine for the ASCII subset of Unicode but obviously
// is bad for everything else. This is unlikely to be an issue given the lack of
// any real internationalization support on the IFS end of things, but might be
// something to look at.
for(int i=0;i< _string.Length; i++)
{
_string[i] = (byte)s[i];
}
}
/// <summary>
/// Build a new BCPL string from the raw representation
/// </summary>
/// <param name="rawData"></param>
public BCPLString(byte[] rawData)
{
if (rawData.Length > 256)
{
throw new InvalidOperationException("Max length for a BCPL string is 255 characters.");
}
// Sanity check that first byte matches length of data sent to us
if (rawData.Length < 1 || rawData[0] != rawData.Length - 1)
{
throw new InvalidOperationException("BCPL length data is invalid.");
}
_string = new byte[rawData.Length - 1];
Array.Copy(rawData, 1, _string, 0, rawData.Length - 1);
}
/// <summary>
/// Build a new BCPL string from the raw representation at the given position in the array
/// </summary>
/// <param name="rawData"></param>
public BCPLString(byte[] rawData, int offset)
{
int length = rawData[offset];
// Sanity check that BCPL length fits within specified array
if (length > rawData.Length - offset)
{
throw new InvalidOperationException("BCPL length data is invalid.");
}
_string = new byte[length];
Array.Copy(rawData, offset + 1, _string, 0, length);
}
public BCPLString(BSPChannel channel)
{
byte length = channel.ReadByte();
_string = new byte[length];
channel.Read(ref _string, length);
}
public BCPLString(Stream s)
{
byte length = (byte)s.ReadByte();
_string = new byte[length];
s.Read(_string, 0, length);
}
public int Length
{
get { return _string.Length; }
}
/// <summary>
/// Returns a native representation of the BCPL string
/// </summary>
/// <returns></returns>
public override string ToString()
{
StringBuilder sb = new StringBuilder();
// See notes in constructor re: unicode.
for (int i = 0; i < _string.Length; i++)
{
sb.Append((char)_string[i]);
}
return sb.ToString();
}
/// <summary>
/// Returns the raw representation of the BCPL string
/// </summary>
/// <returns></returns>
public byte[] ToArray()
{
byte[] a = new byte[_string.Length + 1];
a[0] = (byte)_string.Length;
_string.CopyTo(a, 1);
return a;
}
private byte[] _string;
}
}