243 lines
7.6 KiB
C#
243 lines
7.6 KiB
C#
using System;
|
|
using System.IO;
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
namespace BizHawk.Emulation.Cores.Computers.AppleII
|
|
{
|
|
// barebones classes for writing and reading a simple bson-like format, used to gain a bit of speed in Apple II savestates
|
|
internal enum LBTOK : byte
|
|
{
|
|
Null,
|
|
Undefined,
|
|
StartArray,
|
|
EndArray,
|
|
StartObject,
|
|
EndObject,
|
|
Property,
|
|
S8,
|
|
U8,
|
|
S16,
|
|
U16,
|
|
S32,
|
|
U32,
|
|
S64,
|
|
U64,
|
|
False,
|
|
True,
|
|
String,
|
|
F32,
|
|
F64,
|
|
ByteArray,
|
|
}
|
|
|
|
public class LBR : JsonReader
|
|
{
|
|
private readonly BinaryReader _r;
|
|
private object _v;
|
|
private JsonToken _t;
|
|
|
|
public LBR(BinaryReader reader)
|
|
{
|
|
_r = reader;
|
|
}
|
|
|
|
public override void Close()
|
|
{
|
|
}
|
|
|
|
// as best as I can tell, the serializers refer to depth, but don't actually need to work except when doing certain error recovery
|
|
public override int Depth => 0;
|
|
|
|
public override string Path
|
|
{
|
|
get { throw new NotImplementedException(); }
|
|
}
|
|
|
|
public override Type ValueType => _v?.GetType();
|
|
|
|
public override JsonToken TokenType => _t;
|
|
|
|
public override object Value => _v;
|
|
|
|
public override bool Read()
|
|
{
|
|
LBTOK l = (LBTOK)_r.ReadByte();
|
|
switch (l)
|
|
{
|
|
case LBTOK.StartArray: _t = JsonToken.StartArray; _v = null; break;
|
|
case LBTOK.EndArray: _t = JsonToken.EndArray; _v = null; break;
|
|
case LBTOK.StartObject: _t = JsonToken.StartObject; _v = null; break;
|
|
case LBTOK.EndObject: _t = JsonToken.EndObject; _v = null; break;
|
|
case LBTOK.Null: _t = JsonToken.Null; _v = null; break;
|
|
case LBTOK.False: _t = JsonToken.Boolean; _v = false; break;
|
|
case LBTOK.True: _t = JsonToken.Boolean; _v = true; break;
|
|
case LBTOK.Property: _t = JsonToken.PropertyName; _v = _r.ReadString(); break;
|
|
case LBTOK.Undefined: _t = JsonToken.Undefined; _v = null; break;
|
|
case LBTOK.S8: _t = JsonToken.Integer; _v = _r.ReadSByte(); break;
|
|
case LBTOK.U8: _t = JsonToken.Integer; _v = _r.ReadByte(); break;
|
|
case LBTOK.S16: _t = JsonToken.Integer; _v = _r.ReadInt16(); break;
|
|
case LBTOK.U16: _t = JsonToken.Integer; _v = _r.ReadUInt16(); break;
|
|
case LBTOK.S32: _t = JsonToken.Integer; _v = _r.ReadInt32(); break;
|
|
case LBTOK.U32: _t = JsonToken.Integer; _v = _r.ReadUInt32(); break;
|
|
case LBTOK.S64: _t = JsonToken.Integer; _v = _r.ReadInt64(); break;
|
|
case LBTOK.U64: _t = JsonToken.Integer; _v = _r.ReadUInt64(); break;
|
|
case LBTOK.String: _t = JsonToken.String; _v = _r.ReadString(); break;
|
|
case LBTOK.F32: _t = JsonToken.Float; _v = _r.ReadSingle(); break;
|
|
case LBTOK.F64: _t = JsonToken.Float; _v = _r.ReadDouble(); break;
|
|
case LBTOK.ByteArray: _t = JsonToken.Bytes; _v = _r.ReadBytes(_r.ReadInt32()); break;
|
|
|
|
default:
|
|
throw new InvalidOperationException();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public override byte[] ReadAsBytes()
|
|
{
|
|
if (!Read() || _t != JsonToken.Bytes)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return (byte[])_v;
|
|
}
|
|
|
|
public override DateTime? ReadAsDateTime()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public override DateTimeOffset? ReadAsDateTimeOffset()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public override decimal? ReadAsDecimal()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public override int? ReadAsInt32()
|
|
{
|
|
// TODO: speed this up if needed
|
|
if (!Read())
|
|
{
|
|
return null;
|
|
}
|
|
|
|
switch (_t)
|
|
{
|
|
case JsonToken.Null:
|
|
return null;
|
|
case JsonToken.Integer:
|
|
case JsonToken.Float:
|
|
return Convert.ToInt32(_v);
|
|
case JsonToken.String:
|
|
int i;
|
|
if (int.TryParse(_v.ToString(), out i))
|
|
{
|
|
return i;
|
|
}
|
|
|
|
return null;
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public override string ReadAsString()
|
|
{
|
|
if (!Read())
|
|
{
|
|
return null;
|
|
}
|
|
|
|
switch (_t)
|
|
{
|
|
case JsonToken.Null:
|
|
return null;
|
|
case JsonToken.Float:
|
|
case JsonToken.Integer:
|
|
case JsonToken.Boolean:
|
|
case JsonToken.String:
|
|
return _v.ToString();
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
public class LBW : JsonWriter
|
|
{
|
|
private readonly BinaryWriter w;
|
|
|
|
private void WT(LBTOK t)
|
|
{
|
|
w.Write((byte)t);
|
|
}
|
|
|
|
public LBW(BinaryWriter w)
|
|
{
|
|
this.w = w;
|
|
}
|
|
|
|
public override void Flush()
|
|
{
|
|
w.Flush();
|
|
}
|
|
|
|
public override void Close()
|
|
{
|
|
}
|
|
|
|
public override void WriteValue(bool value) { WT(value ? LBTOK.True : LBTOK.False); }
|
|
|
|
public override void WriteValue(sbyte value) { WT(LBTOK.S8); w.Write(value); }
|
|
public override void WriteValue(byte value) { WT(LBTOK.U8); w.Write(value); }
|
|
public override void WriteValue(short value) { WT(LBTOK.S16); w.Write(value); }
|
|
public override void WriteValue(ushort value) { WT(LBTOK.U16); w.Write(value); }
|
|
public override void WriteValue(int value) { WT(LBTOK.S32); w.Write(value); }
|
|
public override void WriteValue(uint value) { WT(LBTOK.U32); w.Write(value); }
|
|
public override void WriteValue(long value) { WT(LBTOK.S64); w.Write(value); }
|
|
public override void WriteValue(ulong value) { WT(LBTOK.U64); w.Write(value); }
|
|
|
|
public override void WriteStartArray() { WT(LBTOK.StartArray); }
|
|
public override void WriteEndArray() { WT(LBTOK.EndArray); }
|
|
public override void WriteStartObject() { WT(LBTOK.StartObject); }
|
|
public override void WriteEndObject() { WT(LBTOK.EndObject); }
|
|
public override void WriteNull() { WT(LBTOK.Null); }
|
|
public override void WriteUndefined() { WT(LBTOK.Undefined); }
|
|
|
|
public override void WriteValue(float value) { WT(LBTOK.F32); w.Write(value); }
|
|
public override void WriteValue(double value) { WT(LBTOK.F64); w.Write(value); }
|
|
|
|
public override void WriteValue(byte[] value) { WT(LBTOK.ByteArray); w.Write(value.Length); w.Write(value); }
|
|
|
|
public override void WriteComment(string text) { throw new NotImplementedException(); }
|
|
public override void WriteWhitespace(string ws) { throw new NotImplementedException(); }
|
|
protected override void WriteIndent() { throw new NotImplementedException(); }
|
|
protected override void WriteIndentSpace() { throw new NotImplementedException(); }
|
|
public override void WriteEnd() { throw new NotImplementedException(); }
|
|
protected override void WriteEnd(JsonToken token) { throw new NotImplementedException(); }
|
|
public override void WriteRaw(string json) { throw new NotImplementedException(); }
|
|
public override void WriteRawValue(string json) { throw new NotImplementedException(); }
|
|
public override void WriteStartConstructor(string name) { throw new NotImplementedException(); }
|
|
public override void WriteEndConstructor() { throw new NotImplementedException(); }
|
|
protected override void WriteValueDelimiter() { throw new NotImplementedException(); }
|
|
|
|
public override void WritePropertyName(string name) { WT(LBTOK.Property); w.Write(name); }
|
|
public override void WriteValue(string value) { WT(LBTOK.String); w.Write(value); }
|
|
public override void WritePropertyName(string name, bool escape) { WT(LBTOK.Property); w.Write(name); } // no escaping required
|
|
|
|
public override void WriteValue(char value) { throw new NotImplementedException(); }
|
|
public override void WriteValue(DateTime value) { throw new NotImplementedException(); }
|
|
public override void WriteValue(DateTimeOffset value) { throw new NotImplementedException(); }
|
|
public override void WriteValue(decimal value) { throw new NotImplementedException(); }
|
|
public override void WriteValue(Guid value) { throw new NotImplementedException(); }
|
|
public override void WriteValue(TimeSpan value) { throw new NotImplementedException(); }
|
|
public override void WriteValue(Uri value) { throw new NotImplementedException(); }
|
|
}
|
|
}
|