370 lines
15 KiB
C#
370 lines
15 KiB
C#
/*
|
|
* Copyright (c) 2019-2024, Sjofn LLC
|
|
* All rights reserved.
|
|
*
|
|
* - Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* - Redistributions of source code must retain the above copyright notice, this
|
|
* list of conditions and the following disclaimer.
|
|
* - Neither the name of the openmetaverse.co nor the names
|
|
* of its contributors may be used to endorse or promote products derived from
|
|
* this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Text;
|
|
|
|
namespace LibreMetaverse.LslTools
|
|
{
|
|
public class Serialiser
|
|
{
|
|
private static Hashtable tps = new Hashtable();
|
|
private static Hashtable srs = new Hashtable();
|
|
private Hashtable obs = new Hashtable();
|
|
private int id = 100;
|
|
private const string Version = "4.5";
|
|
private TextWriter f;
|
|
private int[] b;
|
|
private int pos;
|
|
private int cl;
|
|
|
|
public Serialiser(TextWriter ff)
|
|
{
|
|
this.f = ff;
|
|
}
|
|
|
|
public Serialiser(int[] bb)
|
|
{
|
|
this.b = bb;
|
|
}
|
|
|
|
static Serialiser()
|
|
{
|
|
Serialiser.srs[(object)Serialiser.SerType.Null] = (object)new Serialiser.ObjectSerialiser(Serialiser.NullSerialise);
|
|
Serialiser.tps[(object)typeof(int)] = (object)Serialiser.SerType.Int;
|
|
Serialiser.srs[(object)Serialiser.SerType.Int] = (object)new Serialiser.ObjectSerialiser(Serialiser.IntSerialise);
|
|
Serialiser.tps[(object)typeof(string)] = (object)Serialiser.SerType.String;
|
|
Serialiser.srs[(object)Serialiser.SerType.String] = (object)new Serialiser.ObjectSerialiser(Serialiser.StringSerialise);
|
|
Serialiser.tps[(object)typeof(Hashtable)] = (object)Serialiser.SerType.Hashtable;
|
|
Serialiser.srs[(object)Serialiser.SerType.Hashtable] = (object)new Serialiser.ObjectSerialiser(Serialiser.HashtableSerialise);
|
|
Serialiser.tps[(object)typeof(char)] = (object)Serialiser.SerType.Char;
|
|
Serialiser.srs[(object)Serialiser.SerType.Char] = (object)new Serialiser.ObjectSerialiser(Serialiser.CharSerialise);
|
|
Serialiser.tps[(object)typeof(bool)] = (object)Serialiser.SerType.Bool;
|
|
Serialiser.srs[(object)Serialiser.SerType.Bool] = (object)new Serialiser.ObjectSerialiser(Serialiser.BoolSerialise);
|
|
Serialiser.tps[(object)typeof(Encoding)] = (object)Serialiser.SerType.Encoding;
|
|
Serialiser.srs[(object)Serialiser.SerType.Encoding] = (object)new Serialiser.ObjectSerialiser(Serialiser.EncodingSerialise);
|
|
Serialiser.tps[(object)typeof(UnicodeCategory)] = (object)Serialiser.SerType.UnicodeCategory;
|
|
Serialiser.srs[(object)Serialiser.SerType.UnicodeCategory] = (object)new Serialiser.ObjectSerialiser(Serialiser.UnicodeCategorySerialise);
|
|
Serialiser.tps[(object)typeof(CSymbol.SymType)] = (object)Serialiser.SerType.Symtype;
|
|
Serialiser.srs[(object)Serialiser.SerType.Symtype] = (object)new Serialiser.ObjectSerialiser(Serialiser.SymtypeSerialise);
|
|
Serialiser.tps[(object)typeof(Charset)] = (object)Serialiser.SerType.Charset;
|
|
Serialiser.srs[(object)Serialiser.SerType.Charset] = (object)new Serialiser.ObjectSerialiser(Charset.Serialise);
|
|
Serialiser.tps[(object)typeof(TokClassDef)] = (object)Serialiser.SerType.TokClassDef;
|
|
Serialiser.srs[(object)Serialiser.SerType.TokClassDef] = (object)new Serialiser.ObjectSerialiser(TokClassDef.Serialise);
|
|
Serialiser.tps[(object)typeof(Dfa)] = (object)Serialiser.SerType.Dfa;
|
|
Serialiser.srs[(object)Serialiser.SerType.Dfa] = (object)new Serialiser.ObjectSerialiser(Dfa.Serialise);
|
|
Serialiser.tps[(object)typeof(ResWds)] = (object)Serialiser.SerType.ResWds;
|
|
Serialiser.srs[(object)Serialiser.SerType.ResWds] = (object)new Serialiser.ObjectSerialiser(ResWds.Serialise);
|
|
Serialiser.tps[(object)typeof(Dfa.Action)] = (object)Serialiser.SerType.Action;
|
|
Serialiser.srs[(object)Serialiser.SerType.Action] = (object)new Serialiser.ObjectSerialiser(Dfa.Action.Serialise);
|
|
Serialiser.tps[(object)typeof(ParserOldAction)] = (object)Serialiser.SerType.ParserOldAction;
|
|
Serialiser.srs[(object)Serialiser.SerType.ParserOldAction] = (object)new Serialiser.ObjectSerialiser(ParserOldAction.Serialise);
|
|
Serialiser.tps[(object)typeof(ParserSimpleAction)] = (object)Serialiser.SerType.ParserSimpleAction;
|
|
Serialiser.srs[(object)Serialiser.SerType.ParserSimpleAction] = (object)new Serialiser.ObjectSerialiser(ParserSimpleAction.Serialise);
|
|
Serialiser.tps[(object)typeof(ParserShift)] = (object)Serialiser.SerType.ParserShift;
|
|
Serialiser.srs[(object)Serialiser.SerType.ParserShift] = (object)new Serialiser.ObjectSerialiser(ParserShift.Serialise);
|
|
Serialiser.tps[(object)typeof(ParserReduce)] = (object)Serialiser.SerType.ParserReduce;
|
|
Serialiser.srs[(object)Serialiser.SerType.ParserReduce] = (object)new Serialiser.ObjectSerialiser(ParserReduce.Serialise);
|
|
Serialiser.tps[(object)typeof(ParseState)] = (object)Serialiser.SerType.ParseState;
|
|
Serialiser.srs[(object)Serialiser.SerType.ParseState] = (object)new Serialiser.ObjectSerialiser(ParseState.Serialise);
|
|
Serialiser.tps[(object)typeof(ParsingInfo)] = (object)Serialiser.SerType.ParsingInfo;
|
|
Serialiser.srs[(object)Serialiser.SerType.ParsingInfo] = (object)new Serialiser.ObjectSerialiser(ParsingInfo.Serialise);
|
|
Serialiser.tps[(object)typeof(CSymbol)] = (object)Serialiser.SerType.CSymbol;
|
|
Serialiser.srs[(object)Serialiser.SerType.CSymbol] = (object)new Serialiser.ObjectSerialiser(CSymbol.Serialise);
|
|
Serialiser.tps[(object)typeof(Literal)] = (object)Serialiser.SerType.Literal;
|
|
Serialiser.srs[(object)Serialiser.SerType.Literal] = (object)new Serialiser.ObjectSerialiser(Literal.Serialise);
|
|
Serialiser.tps[(object)typeof(Production)] = (object)Serialiser.SerType.Production;
|
|
Serialiser.srs[(object)Serialiser.SerType.Production] = (object)new Serialiser.ObjectSerialiser(Production.Serialise);
|
|
Serialiser.tps[(object)typeof(EOF)] = (object)Serialiser.SerType.EOF;
|
|
Serialiser.srs[(object)Serialiser.SerType.EOF] = (object)new Serialiser.ObjectSerialiser(EOF.Serialise);
|
|
}
|
|
|
|
public void VersionCheck()
|
|
{
|
|
if (this.Encode)
|
|
{
|
|
this.Serialise((object)"4.5");
|
|
}
|
|
else
|
|
{
|
|
string str = this.Deserialise() as string;
|
|
if (str == null)
|
|
throw new LslToolsException("Serialisation error - found data from version 4.4 or earlier");
|
|
if (str != "4.5")
|
|
throw new LslToolsException("Serialisation error - expected version 4.5, found data from version " + str);
|
|
}
|
|
}
|
|
|
|
public bool Encode => this.f != null;
|
|
|
|
private void _Write(Serialiser.SerType t)
|
|
{
|
|
this._Write((int)t);
|
|
}
|
|
|
|
public void _Write(int i)
|
|
{
|
|
if (this.cl == 5)
|
|
{
|
|
this.f.WriteLine();
|
|
this.cl = 0;
|
|
}
|
|
++this.cl;
|
|
this.f.Write(i);
|
|
this.f.Write(",");
|
|
}
|
|
|
|
public int _Read()
|
|
{
|
|
return this.b[this.pos++];
|
|
}
|
|
|
|
private static object NullSerialise(object o, Serialiser s)
|
|
{
|
|
return (object)null;
|
|
}
|
|
|
|
private static object IntSerialise(object o, Serialiser s)
|
|
{
|
|
if (!s.Encode)
|
|
return (object)s._Read();
|
|
s._Write((int)o);
|
|
return (object)null;
|
|
}
|
|
|
|
private static object StringSerialise(object o, Serialiser s)
|
|
{
|
|
if (s == null)
|
|
return (object)"";
|
|
var encoding = new UnicodeEncoding();
|
|
if (s.Encode)
|
|
{
|
|
byte[] bytes = encoding.GetBytes((string)o);
|
|
s._Write(bytes.Length);
|
|
foreach (var t in bytes)
|
|
s._Write((int)t);
|
|
|
|
return (object)null;
|
|
}
|
|
int count = s._Read();
|
|
byte[] bytes1 = new byte[count];
|
|
for (int index = 0; index < count; ++index)
|
|
bytes1[index] = (byte)s._Read();
|
|
return (object)encoding.GetString(bytes1, 0, count);
|
|
}
|
|
|
|
private static object HashtableSerialise(object o, Serialiser s)
|
|
{
|
|
if (s == null)
|
|
return (object)new Hashtable();
|
|
Hashtable hashtable = (Hashtable)o;
|
|
if (s.Encode)
|
|
{
|
|
s._Write(hashtable.Count);
|
|
foreach (DictionaryEntry dictionaryEntry in hashtable)
|
|
{
|
|
s.Serialise(dictionaryEntry.Key);
|
|
s.Serialise(dictionaryEntry.Value);
|
|
}
|
|
return (object)null;
|
|
}
|
|
int num = s._Read();
|
|
for (int index1 = 0; index1 < num; ++index1)
|
|
{
|
|
object index2 = s.Deserialise();
|
|
object obj = s.Deserialise();
|
|
hashtable[index2] = obj;
|
|
}
|
|
return (object)hashtable;
|
|
}
|
|
|
|
private static object CharSerialise(object o, Serialiser s)
|
|
{
|
|
var encoding = new UnicodeEncoding();
|
|
if (s.Encode)
|
|
{
|
|
byte[] bytes = encoding.GetBytes(new string((char)o, 1));
|
|
s._Write((int)bytes[0]);
|
|
s._Write((int)bytes[1]);
|
|
return (object)null;
|
|
}
|
|
byte[] bytes1 = new byte[2]
|
|
{
|
|
(byte) s._Read(),
|
|
(byte) s._Read()
|
|
};
|
|
return (object)encoding.GetString(bytes1, 0, 2)[0];
|
|
}
|
|
|
|
private static object BoolSerialise(object o, Serialiser s)
|
|
{
|
|
if (!s.Encode)
|
|
return (object)(s._Read() != 0);
|
|
s._Write(!(bool)o ? 0 : 1);
|
|
return (object)null;
|
|
}
|
|
|
|
private static object EncodingSerialise(object o, Serialiser s)
|
|
{
|
|
if (s.Encode)
|
|
{
|
|
Encoding encoding = (Encoding)o;
|
|
s.Serialise((object)encoding.WebName);
|
|
return (object)null;
|
|
}
|
|
string name = (string)s.Deserialise();
|
|
string str1 = name;
|
|
if (str1 != null)
|
|
{
|
|
string str2 = string.IsInterned(str1);
|
|
if ((object)str2 == (object)"us-ascii")
|
|
return (object)Encoding.ASCII;
|
|
if ((object)str2 == (object)"utf-16")
|
|
return (object)Encoding.Unicode;
|
|
if ((object)str2 == (object)"utf-7")
|
|
#pragma warning disable CS0618
|
|
return (object)Encoding.UTF7;
|
|
#pragma warning restore CS0618
|
|
if ((object)str2 == (object)"utf-8")
|
|
return (object)Encoding.UTF8;
|
|
}
|
|
try
|
|
{
|
|
return (object)Encoding.GetEncoding(name);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new LslToolsException("Unknown encoding " + ex.Message);
|
|
}
|
|
}
|
|
|
|
private static object UnicodeCategorySerialise(object o, Serialiser s)
|
|
{
|
|
if (!s.Encode)
|
|
return (object)(UnicodeCategory)s._Read();
|
|
s._Write((int)o);
|
|
return (object)null;
|
|
}
|
|
|
|
private static object SymtypeSerialise(object o, Serialiser s)
|
|
{
|
|
if (!s.Encode)
|
|
return (object)(CSymbol.SymType)s._Read();
|
|
s._Write((int)o);
|
|
return (object)null;
|
|
}
|
|
|
|
public void Serialise(object o)
|
|
{
|
|
if (o == null)
|
|
this._Write(Serialiser.SerType.Null);
|
|
else if (o is Encoding)
|
|
{
|
|
this._Write(Serialiser.SerType.Encoding);
|
|
Serialiser.EncodingSerialise(o, this);
|
|
}
|
|
else
|
|
{
|
|
Type type = o.GetType();
|
|
if (type.IsClass)
|
|
{
|
|
object ob = this.obs[o];
|
|
if (ob != null)
|
|
{
|
|
this._Write((int)ob);
|
|
return;
|
|
}
|
|
int i = ++this.id;
|
|
this._Write(i);
|
|
this.obs[o] = (object)i;
|
|
}
|
|
object tp = Serialiser.tps[(object)type];
|
|
if (tp == null)
|
|
throw new LslToolsException("unknown type " + type.FullName);
|
|
Serialiser.SerType t = (Serialiser.SerType)tp;
|
|
this._Write(t);
|
|
object obj = ((Serialiser.ObjectSerialiser)Serialiser.srs[(object)t])(o, this);
|
|
}
|
|
}
|
|
|
|
public object Deserialise()
|
|
{
|
|
int num1 = this._Read();
|
|
int num2 = 0;
|
|
if (num1 > 100)
|
|
{
|
|
num2 = num1;
|
|
if (num2 <= this.obs.Count + 100)
|
|
return this.obs[(object)num2];
|
|
num1 = this._Read();
|
|
}
|
|
Serialiser.ObjectSerialiser sr = (Serialiser.ObjectSerialiser)Serialiser.srs[(object)(Serialiser.SerType)num1];
|
|
if (sr == null)
|
|
throw new LslToolsException("unknown type " + (object)num1);
|
|
if (num2 <= 0)
|
|
return sr((object)null, this);
|
|
object o = sr((object)null, (Serialiser)null);
|
|
this.obs[(object)num2] = o;
|
|
object obj = sr(o, this);
|
|
this.obs[(object)num2] = obj;
|
|
return obj;
|
|
}
|
|
|
|
private enum SerType
|
|
{
|
|
Null,
|
|
Int,
|
|
Bool,
|
|
Char,
|
|
String,
|
|
Hashtable,
|
|
Encoding,
|
|
UnicodeCategory,
|
|
Symtype,
|
|
Charset,
|
|
TokClassDef,
|
|
Action,
|
|
Dfa,
|
|
ResWds,
|
|
ParserOldAction,
|
|
ParserSimpleAction,
|
|
ParserShift,
|
|
ParserReduce,
|
|
ParseState,
|
|
ParsingInfo,
|
|
CSymbol,
|
|
Literal,
|
|
Production,
|
|
EOF,
|
|
}
|
|
|
|
private delegate object ObjectSerialiser(object o, Serialiser s);
|
|
}
|
|
}
|