using System; using System.Globalization; using System.Text; using Decal.Adapter.NetParser; using Decal.Adapter.Support; namespace Decal.Adapter; /// /// Represents Message data /// public class MessageStruct : MarshalByRefObject { internal struct MessageField { internal string Name; internal MemberParserType Type; internal object Value; internal int Offset; internal int Length; } internal byte[] mData; internal int mOffset; internal int mLength; internal MemberParser mParser; internal MessageStruct mParent; internal int mIndex; internal bool mParsed; internal int mCount; internal MessageField[] mFields; /// /// Returns the number of fields (or vector length) /// public virtual int Count { get { if (!mParsed) { Parse(); } return mCount; } } /// /// Returns the specified field data /// /// Field index /// Field value public virtual object this[int index] { get { if (!mParsed) { Parse(); } if (index >= 0 && index < mCount) { return mFields[index].Value; } return null; } } /// /// Returns the specified field data /// /// Field name /// Field value public virtual object this[string name] { get { if (!mParsed) { Parse(); } int num = IndexFromName(name); if (num >= 0 && num < mCount) { return mFields[num].Value; } return null; } } /// /// Returns the raw bytes for this field /// public virtual byte[] RawData { get { if (mParent != null) { return mParent.RawValue(mIndex); } byte[] array = (byte[])Array.CreateInstance(typeof(byte), mData.Length); Buffer.BlockCopy(mData, 0, array, 0, mData.Length); return array; } } /// /// Returns the next object in the (parent) vector /// public virtual object Next { get { if (mParent == null) { return null; } return mParent[mIndex + 1]; } } /// /// Returns the parent field /// public virtual MessageStruct Parent => mParent; internal MessageStruct() { } internal MessageStruct(byte[] Data, int Offset, MemberParser Parser) { mData = (byte[])Array.CreateInstance(typeof(byte), Data.Length); Buffer.BlockCopy(Data, 0, mData, 0, mData.Length); mOffset = Offset; mParser = Parser; mCount = -1; } internal MessageStruct(byte[] Data, int Offset, MemberParser Parser, MessageStruct Parent, int Index) { mData = Data; mOffset = Offset; mParser = Parser; mParent = Parent; mIndex = Index; mCount = -1; } internal MessageStruct(byte[] Data, int Offset, MemberParser Parser, int Length, MessageStruct Parent, int Index) { mData = Data; mOffset = Offset; mParser = Parser; mParent = Parent; mIndex = Index; mCount = Length; } internal int ObjectToIndex(object vIndex) { string text = vIndex as string; int num = -1; num = (string.IsNullOrEmpty(text) ? Util.UnboxTo(vIndex) : IndexFromName(text)); if (num >= 0 && num < mCount) { return num; } return -1; } /// /// Return the field name for the specified index /// /// Field index /// Name of the field public virtual string Name(int index) { if (!mParsed) { Parse(); } if (index >= 0 && index < mCount) { return mFields[index].Name; } return null; } /// /// Returns the passed in value? /// /// /// public virtual string Name(string memberName) { if (!mParsed) { Parse(); } int num = IndexFromName(memberName); if (num >= 0 && num < mCount) { return mFields[num].Name; } return null; } /// /// Returns the specified child structure /// /// Field index /// MessageStruct for the specified field public virtual MessageStruct Struct(int index) { if (!mParsed) { Parse(); } if (index >= 0 && index < mCount) { MemberParserType type = mFields[index].Type; if (type == MemberParserType.Struct || type == MemberParserType.Vector) { return mFields[index].Value as MessageStruct; } } return null; } /// /// Returns the specified child structure /// /// Field name /// MessageStruct for the specified field public virtual MessageStruct Struct(string name) { if (!mParsed) { Parse(); } int num = IndexFromName(name); if (num >= 0 && num < mCount) { MemberParserType type = mFields[num].Type; if (type == MemberParserType.Struct || type == MemberParserType.Vector) { return mFields[num].Value as MessageStruct; } } return null; } /// /// Returns the specified field value /// /// Type of the field /// Field index /// Field value cast to the specified FieldType public virtual FieldType Value(int index) { if (!mParsed) { Parse(); } if (index >= 0 && index < mCount) { return Util.UnboxTo(mFields[index].Value); } return default(FieldType); } /// /// Returns the specified field value /// /// Type of the field /// Field name /// Field value cast to the specified FieldType public virtual FieldType Value(string name) { if (!mParsed) { Parse(); } int num = IndexFromName(name); if (num >= 0 && num < mCount) { return Util.UnboxTo(mFields[num].Value); } return default(FieldType); } /// /// Returns the raw bytes of the specified field /// /// Field index /// Raw field value public virtual byte[] RawValue(int index) { if (!mParsed) { Parse(); } if (index >= 0 && index < mCount) { int length = mFields[index].Length; byte[] array = (byte[])Array.CreateInstance(typeof(byte), length); Buffer.BlockCopy(mData, mFields[index].Offset, array, 0, length); return array; } return null; } /// /// Returns the raw bytes of the specified field /// /// Field name /// Raw field value public virtual byte[] RawValue(string name) { if (!mParsed) { Parse(); } int num = IndexFromName(name); if (num >= 0 && num < mCount) { int length = mFields[num].Length; byte[] array = (byte[])Array.CreateInstance(typeof(byte), length); Buffer.BlockCopy(mData, mFields[num].Offset, array, 0, length); return array; } return null; } internal int IndexFromName(string Name) { int num = mCount; for (int i = 0; i < num; i++) { if (string.Compare(Name, mFields[i].Name, ignoreCase: true, CultureInfo.InvariantCulture) == 0) { return i; } } return -1; } internal void Parse() { if (mCount == -1) { ParseStruct(); } else { ParseVector(); } } internal void ParseStruct() { int length = ParseCounter(mParser); mFields = (MessageField[])Array.CreateInstance(typeof(MessageField), length); mParsed = true; int ByteIndex = mOffset; mCount = 0; ParseHelper(mParser, ref mCount, ref ByteIndex); mLength = ByteIndex - mOffset; MessageField[] sourceArray = mFields; mFields = (MessageField[])Array.CreateInstance(typeof(MessageField), mCount); Array.Copy(sourceArray, mFields, mCount); } internal void ParseVector() { int num = mCount; mFields = (MessageField[])Array.CreateInstance(typeof(MessageField), num); mParsed = true; int num2 = mOffset; for (int i = 0; i < num; i++) { mFields[i].Name = i.ToString(); mFields[i].Offset = num2; mFields[i].Type = MemberParserType.Struct; MessageStruct messageStruct = new MessageStruct(mData, num2, mParser, this, i); messageStruct.ParseStruct(); mFields[i].Value = messageStruct; mFields[i].Length = messageStruct.mLength; num2 += messageStruct.mLength; } mLength = num2 - mOffset; } internal int ParseCounter(MemberParser Parser) { int num = 0; while (Parser != null) { num = ((Parser.MemberType != MemberParserType.Case) ? (num + 1) : (num + ParseCounter(Parser.Child))); Parser = Parser.Next; } return num; } internal void ParseHelper(MemberParser Parser, ref int FieldIndex, ref int ByteIndex) { Encoding encoding = Encoding.GetEncoding(1252); while (Parser != null) { if (Parser.PreAlignment != 0) { int num = ByteIndex % Parser.PreAlignment; if (num != 0) { ByteIndex += Parser.PreAlignment - num; } } bool flag = Parser.Condition == MemberParserCondition.None; if (!flag) { MessageStruct messageStruct = this; object obj; do { obj = messageStruct[Parser.ConditionField]; if (obj != null) { break; } messageStruct = messageStruct.mParent; } while (messageStruct != null); if (obj != null) { long num2 = 0L; Type type = obj.GetType(); if (type.Equals(typeof(int))) { num2 = Convert.ToInt64(obj); num2 &= 0xFFFFFFFFu; } else if (type.Equals(typeof(short))) { num2 = Convert.ToInt64(obj); num2 &= 0xFFFF; } else if (type.Equals(typeof(byte))) { num2 = Convert.ToInt64(obj); num2 &= 0xFF; } else if (type.Equals(typeof(long))) { num2 = Convert.ToInt64(obj); } num2 ^= Parser.ConditionXor; num2 &= Parser.ConditionAnd; switch (Parser.Condition) { case MemberParserCondition.EQ: flag = num2 == Parser.ConditionResult; break; case MemberParserCondition.NE: flag = num2 != Parser.ConditionResult; break; case MemberParserCondition.GE: flag = num2 >= Parser.ConditionResult; break; case MemberParserCondition.GT: flag = num2 > Parser.ConditionResult; break; case MemberParserCondition.LE: flag = num2 <= Parser.ConditionResult; break; case MemberParserCondition.LT: flag = num2 < Parser.ConditionResult; break; } } } if (flag) { mFields[FieldIndex].Name = Parser.MemberName; mFields[FieldIndex].Offset = ByteIndex; mFields[FieldIndex].Type = Parser.MemberType; switch (Parser.MemberType) { case MemberParserType.BYTE: mFields[FieldIndex].Value = mData[ByteIndex++]; break; case MemberParserType.WORD: mFields[FieldIndex].Value = BitConverter.ToInt16(mData, ByteIndex); ByteIndex += 2; break; case MemberParserType.PackedWORD: { int num6 = mData[ByteIndex++]; if ((num6 & 0x80) != 0) { num6 = ((num6 & 0x7F) << 8) | mData[ByteIndex++]; } mFields[FieldIndex].Value = num6; break; } case MemberParserType.DWORD: mFields[FieldIndex].Value = BitConverter.ToInt32(mData, ByteIndex); ByteIndex += 4; break; case MemberParserType.PackedDWORD: { int num6 = BitConverter.ToInt16(mData, ByteIndex); ByteIndex += 2; if ((num6 & 0x8000) != 0) { num6 = ((num6 & 0x7FFF) << 16) | (BitConverter.ToInt16(mData, ByteIndex) & 0xFFFF); ByteIndex += 2; } mFields[FieldIndex].Value = num6; break; } case MemberParserType.QWORD: mFields[FieldIndex].Value = BitConverter.ToInt64(mData, ByteIndex); ByteIndex += 8; break; case MemberParserType.@float: mFields[FieldIndex].Value = BitConverter.ToSingle(mData, ByteIndex); ByteIndex += 4; break; case MemberParserType.@double: mFields[FieldIndex].Value = BitConverter.ToDouble(mData, ByteIndex); ByteIndex += 8; break; case MemberParserType.String: { int num6 = BitConverter.ToInt16(mData, ByteIndex); ByteIndex += 2; if (num6 == -1) { num6 = BitConverter.ToInt32(mData, ByteIndex); ByteIndex += 4; } StringBuilder stringBuilder = new StringBuilder(num6); for (int j = 0; j < num6; j++) { stringBuilder.Append(encoding.GetChars(mData, ByteIndex++, 1)); } mFields[FieldIndex].Value = stringBuilder.ToString(); ByteIndex = (ByteIndex + 3) & -4; break; } case MemberParserType.WString: { int num6 = mData[ByteIndex++]; if ((num6 & 0x80) != 0) { num6 = ((num6 & 0x7F) << 8) | mData[ByteIndex++]; } StringBuilder stringBuilder = new StringBuilder(num6); for (int i = 0; i < num6; i++) { stringBuilder.Append(BitConverter.ToChar(mData, ByteIndex)); ByteIndex += 2; } mFields[FieldIndex].Value = stringBuilder.ToString(); break; } case MemberParserType.Struct: { MessageStruct messageStruct = new MessageStruct(mData, ByteIndex, Parser.Child, this, FieldIndex); messageStruct.ParseStruct(); ByteIndex += messageStruct.mLength; mFields[FieldIndex].Value = messageStruct; break; } case MemberParserType.Vector: { MessageStruct messageStruct = this; object obj; do { obj = messageStruct[Parser.LengthField]; if (obj != null) { break; } messageStruct = messageStruct.mParent; } while (messageStruct != null); long num4 = 0L; if (obj != null) { Type type2 = obj.GetType(); if (type2.Equals(typeof(int))) { num4 = Convert.ToInt64(obj); num4 &= 0xFFFFFFFFu; } else if (type2.Equals(typeof(short))) { num4 = Convert.ToInt64(obj); num4 &= 0xFFFF; } else if (type2.Equals(typeof(byte))) { num4 = Convert.ToInt64(obj); num4 &= 0xFF; } else if (type2.Equals(typeof(long))) { num4 = Convert.ToInt64(obj); } } long num5 = Parser.LengthMask; num4 &= num5; if (num5 != 0L) { while ((num5 & 1) == 0L) { num4 >>= 1; num5 >>= 1; } } messageStruct = new MessageStruct(mData, ByteIndex, Parser.Child, (int)num4 + Parser.LengthDelta, this, FieldIndex); messageStruct.ParseVector(); ByteIndex += messageStruct.mLength; mFields[FieldIndex].Value = messageStruct; break; } case MemberParserType.Case: { int num3 = FieldIndex; ParseHelper(Parser.Child, ref FieldIndex, ref ByteIndex); if (FieldIndex > num3) { FieldIndex--; } break; } } mFields[FieldIndex].Length = ByteIndex - mFields[FieldIndex].Offset; } if (Parser.PostAlignment != 0) { int num7 = ByteIndex % Parser.PostAlignment; if (num7 != 0) { num7 = Parser.PostAlignment - num7; ByteIndex += num7; if (flag) { mFields[FieldIndex].Length += num7; } } } if (flag) { FieldIndex++; } Parser = Parser.Next; } } }