Created
January 3, 2011 19:58
-
-
Save Konctantin/763862 to your computer and use it in GitHub Desktop.
Implement Xml Desirealiser for Swith segment
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From cf8f47d667e569c7a3ec5c5c9855ca595d3696ad Mon Sep 17 00:00:00 2001 | |
From: Konctantin <[email protected]> | |
Date: Mon, 3 Jan 2011 21:56:08 +0200 | |
Subject: [PATCH] Implement Xml Desirealiser for Swith segment | |
* small restucturisation of XmlParser | |
this is Alpfa version, need test | |
Signed-off-by: Konctantin <[email protected]> | |
--- | |
PacketViewer/PacketViewer.csproj | 2 + | |
.../XML/Packet Segments/FinalListPacketSegment.cs | 9 +- | |
.../XML/Packet Segments/ListPacketSegment.cs | 50 ++-- | |
.../XML/Packet Segments/SimplePacketSegment.cs | 16 +- | |
.../XML/Packet Segments/StaticListPacketSegment.cs | 9 +- | |
.../Parsers/XML/Packet Segments/SwitchCase.cs | 331 ++++++++++++++++++++ | |
.../XML/Packet Segments/SwitchPacketSegment.cs | 133 ++++++++ | |
PacketViewer/Parsers/XML/XmlPacketDefinitions.cs | 29 +- | |
PacketViewer/Parsers/XML/XmlParser.cs | 9 +- | |
PacketViewer/Parsers/XML/XmlTypeReader.cs | 80 +++-- | |
10 files changed, 585 insertions(+), 83 deletions(-) | |
create mode 100644 PacketViewer/Parsers/XML/Packet Segments/SwitchCase.cs | |
create mode 100644 PacketViewer/Parsers/XML/Packet Segments/SwitchPacketSegment.cs | |
diff --git a/PacketViewer/PacketViewer.csproj b/PacketViewer/PacketViewer.csproj | |
index f26d01a..093dc2d 100644 | |
--- a/PacketViewer/PacketViewer.csproj | |
+++ b/PacketViewer/PacketViewer.csproj | |
@@ -201,6 +201,8 @@ | |
<Compile Include="Parsers\XML\Packet Segments\FinalListPacketSegment.cs" /> | |
<Compile Include="Parsers\XML\Packet Segments\ListPacketSegment.cs" /> | |
<Compile Include="Parsers\XML\Packet Segments\StaticListPacketSegment.cs" /> | |
+ <Compile Include="Parsers\XML\Packet Segments\SwitchPacketSegment.cs" /> | |
+ <Compile Include="Parsers\XML\Packet Segments\SwitchCase.cs" /> | |
<Compile Include="Parsers\XML\XmlPacketDefinitions.cs" /> | |
<Compile Include="Parsers\XML\XmlParser.cs" /> | |
<Compile Include="Parsers\XML\Packet Segments\SimplePacketSegment.cs" /> | |
diff --git a/PacketViewer/Parsers/XML/Packet Segments/FinalListPacketSegment.cs b/PacketViewer/Parsers/XML/Packet Segments/FinalListPacketSegment.cs | |
index ff1d038..8273c8c 100644 | |
--- a/PacketViewer/Parsers/XML/Packet Segments/FinalListPacketSegment.cs | |
+++ b/PacketViewer/Parsers/XML/Packet Segments/FinalListPacketSegment.cs | |
@@ -1,5 +1,7 @@ | |
using System; | |
using System.IO; | |
+using System.Text; | |
+using Kamilla; | |
namespace PacketViewer.Parsers.XML | |
{ | |
@@ -17,13 +19,14 @@ namespace PacketViewer.Parsers.XML | |
/// <returns>The parsed string.</returns> | |
public override string Parse(BinaryReader Reader, IXmlPacketSegmentContainer Container) | |
{ | |
- string content = "List of " + this.SegmentName + ":" + Environment.NewLine; | |
+ StringBuilder content = new StringBuilder(); | |
+ content.AppendFormatLine("List of {0}:", this.SegmentName); | |
ulong i = 0; | |
while (Reader.BaseStream.Position < Reader.BaseStream.Length) | |
- content += ParseList(i++, Reader, this); | |
+ content.Append(ParseList(i++, Reader, this)); | |
- return content; | |
+ return content.ToString(); | |
} | |
} | |
} | |
diff --git a/PacketViewer/Parsers/XML/Packet Segments/ListPacketSegment.cs b/PacketViewer/Parsers/XML/Packet Segments/ListPacketSegment.cs | |
index 4e5fc3a..95d7179 100644 | |
--- a/PacketViewer/Parsers/XML/Packet Segments/ListPacketSegment.cs | |
+++ b/PacketViewer/Parsers/XML/Packet Segments/ListPacketSegment.cs | |
@@ -1,6 +1,7 @@ | |
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
+using System.Text; | |
using System.Xml.Serialization; | |
using Kamilla; | |
@@ -32,17 +33,17 @@ namespace PacketViewer.Parsers.XML | |
/// <returns>The parsed string.</returns> | |
public override string Parse(BinaryReader Reader, IXmlPacketSegmentContainer Container) | |
{ | |
- string content = string.Empty; | |
+ StringBuilder content = new StringBuilder(); | |
- if (String.IsNullOrEmpty(LengthSegmentName)) | |
+ if (string.IsNullOrEmpty(LengthSegmentName)) | |
{ | |
- content = "List (" + base.Parse(Reader, Container) + ")" + Environment.NewLine; | |
- this.Length = ulong.Parse(base.Value); | |
+ content.AppendFormatLine("List ({0})", base.Parse(Reader, Container)); | |
+ this.Length = Convert.ToUInt64(base.Value); | |
} | |
else | |
{ | |
XmlPacketSegment lengthSegment = null; | |
- foreach (XmlPacketSegment segment in Container.GetContainedSegments()) | |
+ foreach (XmlPacketSegment segment in Container.ContainedSegments) | |
{ | |
if (segment.SegmentName == LengthSegmentName) | |
lengthSegment = segment; | |
@@ -50,8 +51,8 @@ namespace PacketViewer.Parsers.XML | |
if (lengthSegment != null) | |
{ | |
- content = "List (" + LengthSegmentName + ": " + lengthSegment.Value + ")" + Environment.NewLine; | |
- this.Length = ulong.Parse(lengthSegment.Value); | |
+ content.AppendFormatLine("List ({0}: {1})", LengthSegmentName, lengthSegment.Value); | |
+ this.Length = Convert.ToUInt64(lengthSegment.Value); | |
} | |
else | |
throw new Exception("Failed to find Length Segment with name '" + LengthSegmentName + "'"); | |
@@ -65,9 +66,9 @@ namespace PacketViewer.Parsers.XML | |
// Member2: 4 | |
for (ulong i = 0; i < this.Length; ++i) | |
- content += ParseList(i, Reader, this); | |
+ content.Append(ParseList(i, Reader, this)); | |
- return content; | |
+ return content.ToString(); | |
} | |
/// <summary> | |
@@ -81,21 +82,20 @@ namespace PacketViewer.Parsers.XML | |
{ | |
// 1) Member1: 3 | |
// Member2: 4 | |
- | |
- string content = index.ToString().PadLeft(3) + ") "; | |
+ StringBuilder content = new StringBuilder(index.ToString().PadLeft(3) + ") "); | |
bool first = true; | |
- foreach (XmlPacketSegment segment in List.GetContainedSegments()) | |
+ foreach (XmlPacketSegment segment in List.ContainedSegments) | |
{ | |
if (!first) | |
- content += string.Empty.PadRight(5); | |
+ content.Append(string.Empty.PadRight(5)); | |
else | |
first = false; | |
- content += segment.Parse(Reader, List).PadMultiline(5) + Environment.NewLine; | |
+ content.AppendLine(segment.Parse(Reader, List).PadMultiline(5)); | |
} | |
- return content; | |
+ return content.ToString(); | |
} | |
/// <summary> | |
@@ -103,17 +103,21 @@ namespace PacketViewer.Parsers.XML | |
/// </summary> | |
/* | |
[XmlElement("FinalList", typeof(FinalListPacketSegment), Order = 4)] | |
- [XmlElement("Switch", typeof(SwitchPacketSegment), Order = 4)] | |
- */ | |
- [XmlElement("StaticList", typeof(StaticListPacketSegment), Order = 4)] | |
- [XmlElement("List", typeof(ListPacketSegment), Order = 4)] | |
- [XmlElement("Simple", typeof(SimplePacketSegment), Order = 4)] | |
+ */ | |
+ [XmlElement("Switch", typeof(SwitchPacketSegment), Order = 4)] | |
+ [XmlElement("StaticList", typeof(StaticListPacketSegment), Order = 4)] | |
+ [XmlElement("List", typeof(ListPacketSegment), Order = 4)] | |
+ [XmlElement("Simple", typeof(SimplePacketSegment), Order = 4)] | |
public List<XmlPacketSegment> Elements; | |
/// <summary> | |
- /// Implements <see cref="IXmlPacketSegmentContainer.GetContainedSegments"/>. | |
+ /// Implements <see cref="IXmlPacketSegmentContainer.ContainedSegments"/>. | |
/// </summary> | |
/// <returns>The list of packet segments of the current list segment.</returns> | |
- public List<XmlPacketSegment> GetContainedSegments() { return Elements; } | |
+ [XmlIgnore] | |
+ public List<XmlPacketSegment> ContainedSegments | |
+ { | |
+ get { return Elements; } | |
+ } | |
} | |
-} | |
+} | |
\ No newline at end of file | |
diff --git a/PacketViewer/Parsers/XML/Packet Segments/SimplePacketSegment.cs b/PacketViewer/Parsers/XML/Packet Segments/SimplePacketSegment.cs | |
index 8d0da7c..5a5bc49 100644 | |
--- a/PacketViewer/Parsers/XML/Packet Segments/SimplePacketSegment.cs | |
+++ b/PacketViewer/Parsers/XML/Packet Segments/SimplePacketSegment.cs | |
@@ -1,5 +1,6 @@ | |
using System; | |
using System.IO; | |
+using System.Text; | |
using Kamilla; | |
namespace PacketViewer.Parsers.XML | |
@@ -19,23 +20,30 @@ namespace PacketViewer.Parsers.XML | |
/// <returns>The parsed string.</returns> | |
public override string Parse(BinaryReader Reader, IXmlPacketSegmentContainer Container) | |
{ | |
+ StringBuilder output = new StringBuilder(); | |
+ string header = this.SegmentName + ": "; | |
+ | |
Value = XmlTypeReader.Read(Reader, SimpleType); | |
if (!String.IsNullOrEmpty(this.EnumName)) | |
{ | |
Type T = Type.GetType(this.EnumName); | |
+ | |
if (T == null) | |
T = Type.GetType("Kamilla.WorldOfWarcraft." + this.EnumName + ", Kamilla.WorldOfWarcraft"); | |
if (T == null) | |
throw new Exception("Type " + this.EnumName + " cannot be found."); | |
- Value = String.Format("{0} ({0:D})", Enum.Parse(T, Value)); | |
+ Value = Enum.Parse(T, Value.ToString()); | |
+ output.AppendFormat("{0} ({0:D})", Value); | |
+ } | |
+ else | |
+ { | |
+ output.AppendFormat("{0}", Value); | |
} | |
- string header = this.SegmentName + ": "; | |
- | |
- return header + Value.PadMultiline(header.Length); | |
+ return header + output.ToString().PadMultiline(header.Length); | |
} | |
} | |
} | |
diff --git a/PacketViewer/Parsers/XML/Packet Segments/StaticListPacketSegment.cs b/PacketViewer/Parsers/XML/Packet Segments/StaticListPacketSegment.cs | |
index 1cf2e27..2d3cac2 100644 | |
--- a/PacketViewer/Parsers/XML/Packet Segments/StaticListPacketSegment.cs | |
+++ b/PacketViewer/Parsers/XML/Packet Segments/StaticListPacketSegment.cs | |
@@ -1,6 +1,8 @@ | |
using System; | |
using System.IO; | |
+using System.Text; | |
using System.Xml.Serialization; | |
+using Kamilla; | |
namespace PacketViewer.Parsers.XML | |
{ | |
@@ -24,7 +26,8 @@ namespace PacketViewer.Parsers.XML | |
/// <returns>The parsed string.</returns> | |
public override string Parse(BinaryReader Reader, IXmlPacketSegmentContainer Container) | |
{ | |
- string content = "Static List (" + this.SegmentName + ": " + this.Length + ")" + Environment.NewLine; | |
+ StringBuilder content = new StringBuilder(); | |
+ content.AppendFormatLine("Static List ({0}: {1})", this.SegmentName, this.Length); | |
// This looks like this: | |
// List (Static Count: 2) -- Header. | |
@@ -34,9 +37,9 @@ namespace PacketViewer.Parsers.XML | |
// Member2: 4 | |
for (ulong i = 0; i < this.Length; ++i) | |
- content += ParseList(i, Reader, this); | |
+ content.Append(ParseList(i, Reader, this)); | |
- return content; | |
+ return content.ToString(); | |
} | |
} | |
} | |
diff --git a/PacketViewer/Parsers/XML/Packet Segments/SwitchCase.cs b/PacketViewer/Parsers/XML/Packet Segments/SwitchCase.cs | |
new file mode 100644 | |
index 0000000..50fcf94 | |
--- /dev/null | |
+++ b/PacketViewer/Parsers/XML/Packet Segments/SwitchCase.cs | |
@@ -0,0 +1,331 @@ | |
+using System; | |
+using System.IO; | |
+using System.Collections.Generic; | |
+using System.Text; | |
+using System.Xml.Serialization; | |
+using Kamilla; | |
+ | |
+namespace PacketViewer.Parsers.XML | |
+{ | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ public enum ComparisonType | |
+ { | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ Equal, | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ NotEqual, | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ GreaterThan, | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ LessThan, | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ GreaterOrEqual, | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ LessOrEqual, | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ And, | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ AndExclusive, | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ AndNot, | |
+ } | |
+ | |
+ /// <summary> | |
+ /// A PacketSegmentStructure-wrapper whose content decides a switch in another segment of the packet | |
+ /// </summary> | |
+ public class SwitchCase : SimplePacketSegment, IXmlPacketSegmentContainer | |
+ { | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ /// <param name="switchCase"></param> | |
+ /// <param name="val"></param> | |
+ /// <returns></returns> | |
+ public delegate bool SwitchComparer(SwitchCase switchCase, object val); | |
+ | |
+ private object ConditionValue; | |
+ | |
+ private SwitchComparer m_comparer; | |
+ | |
+ private static Dictionary<ComparisonType, SwitchComparer> Matchers = new Dictionary<ComparisonType, SwitchComparer>(); | |
+ | |
+ static SwitchCase() | |
+ { | |
+ Matchers[ComparisonType.Equal] = (condition, value) => | |
+ { | |
+ return condition.ConditionValue.Equals(value); | |
+ }; | |
+ | |
+ Matchers[ComparisonType.NotEqual] = (condition, value) => | |
+ { | |
+ return !condition.ConditionValue.Equals(value); | |
+ }; | |
+ | |
+ Matchers[ComparisonType.GreaterThan] = (condition, value) => | |
+ { | |
+ return condition.ToComparable(condition.ConditionValue).CompareTo(condition.ToComparable(value)) < 0; | |
+ }; | |
+ | |
+ Matchers[ComparisonType.LessThan] = (condition, value) => | |
+ { | |
+ return condition.ToComparable(condition.ConditionValue).CompareTo(condition.ToComparable(value)) > 0; | |
+ }; | |
+ | |
+ Matchers[ComparisonType.GreaterOrEqual] = (condition, value) => | |
+ { | |
+ return condition.ToComparable(condition.ConditionValue).CompareTo(condition.ToComparable(value)) <= 0; | |
+ }; | |
+ | |
+ Matchers[ComparisonType.LessOrEqual] = (condition, value) => | |
+ { | |
+ return condition.ToComparable(condition.ConditionValue).CompareTo(condition.ToComparable(value)) >= 0; | |
+ }; | |
+ | |
+ Matchers[ComparisonType.And] = (condition, value) => | |
+ { | |
+ long cmpFlags = (long)Convert.ChangeType(condition.ConditionValue, typeof(long)); | |
+ long flags = (long)Convert.ChangeType(value, typeof(long)); | |
+ | |
+ return (cmpFlags & flags) != 0; | |
+ }; | |
+ | |
+ Matchers[ComparisonType.AndNot] = (condition, value) => | |
+ { | |
+ long cmpFlags = (long)Convert.ChangeType(condition.ConditionValue, typeof(long)); | |
+ long flags = (long)Convert.ChangeType(value, typeof(long)); | |
+ | |
+ return (cmpFlags & flags) == 0; | |
+ }; | |
+ | |
+ Matchers[ComparisonType.AndExclusive] = (condition, value) => | |
+ { | |
+ long cmpFlags = (long)Convert.ChangeType(condition.ConditionValue, typeof(long)); | |
+ long flags = (long)Convert.ChangeType(value, typeof(long)); | |
+ | |
+ return (cmpFlags & flags) == cmpFlags; | |
+ }; | |
+ } | |
+ | |
+ private IComparable ToComparable(object value) | |
+ { | |
+ if (value is IComparable) | |
+ return (IComparable)value; | |
+ | |
+ throw new Exception( | |
+ string.Format("Could not parse given value '{0}' since its Type '{1}' is not implementing IComparable", | |
+ value, value.GetType())); | |
+ } | |
+ | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ /// <param name="condVal"></param> | |
+ /// <param name="value"></param> | |
+ /// <returns></returns> | |
+ public bool Matches(object condVal, object value) | |
+ { | |
+ ConditionValue = condVal; | |
+ try | |
+ { | |
+ return m_comparer(this, value); | |
+ } | |
+ catch (Exception ex) | |
+ { | |
+ throw new Exception( | |
+ string.Format("Could not match its value '{0}' against parsed value: {1}", | |
+ ConditionValue, value), ex); | |
+ } | |
+ } | |
+ | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ /// <param name="Reader"></param> | |
+ /// <param name="Container"></param> | |
+ /// <returns></returns> | |
+ public override string Parse(BinaryReader Reader, IXmlPacketSegmentContainer Container) | |
+ { | |
+ StringBuilder content = new StringBuilder(); | |
+ foreach (XmlPacketSegment segment in Elements) | |
+ { | |
+ content.AppendLine(" " + segment.Parse(Reader, Container)); | |
+ } | |
+ return content.ToString(); | |
+ } | |
+ | |
+ #region Serialisator | |
+ | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ [XmlAttribute("Equals")] | |
+ public string EqualValue | |
+ { | |
+ get { return StrValue; } | |
+ set | |
+ { | |
+ m_comparer = Matchers[ComparisonType.Equal]; | |
+ StrValue = value; | |
+ } | |
+ } | |
+ | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ [XmlAttribute("NotEqual")] | |
+ public string NotEqualValue | |
+ { | |
+ get { return StrValue; } | |
+ set | |
+ { | |
+ m_comparer = Matchers[ComparisonType.NotEqual]; | |
+ StrValue = value; | |
+ } | |
+ } | |
+ | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ [XmlAttribute("GreaterThan")] | |
+ public string GreaterThanValue | |
+ { | |
+ get { return StrValue; } | |
+ set | |
+ { | |
+ m_comparer = Matchers[ComparisonType.GreaterThan]; | |
+ StrValue = value; | |
+ } | |
+ } | |
+ | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ [XmlAttribute("GreaterOrEqual")] | |
+ public string GreaterOrEqualValue | |
+ { | |
+ get { return StrValue; } | |
+ set | |
+ { | |
+ m_comparer = Matchers[ComparisonType.GreaterOrEqual]; | |
+ StrValue = value; | |
+ } | |
+ } | |
+ | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ [XmlAttribute("LessThan")] | |
+ public string LessThanValue | |
+ { | |
+ get { return StrValue; } | |
+ set | |
+ { | |
+ m_comparer = Matchers[ComparisonType.LessThan]; | |
+ StrValue = value; | |
+ } | |
+ } | |
+ | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ [XmlAttribute("LessOrEqual")] | |
+ public string LessOrEqualValue | |
+ { | |
+ get { return StrValue; } | |
+ set | |
+ { | |
+ m_comparer = Matchers[ComparisonType.LessOrEqual]; | |
+ StrValue = value; | |
+ } | |
+ } | |
+ | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ [XmlAttribute("And")] | |
+ public string AndValue | |
+ { | |
+ get { return StrValue; } | |
+ set | |
+ { | |
+ m_comparer = Matchers[ComparisonType.And]; | |
+ StrValue = value; | |
+ } | |
+ } | |
+ | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ [XmlAttribute("AndExclusive")] | |
+ public string AndExclusiveValue | |
+ { | |
+ get { return StrValue; } | |
+ set | |
+ { | |
+ m_comparer = Matchers[ComparisonType.AndExclusive]; | |
+ StrValue = value; | |
+ } | |
+ } | |
+ | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ [XmlAttribute("AndNot")] | |
+ public string AndNotValue | |
+ { | |
+ get { return StrValue; } | |
+ set | |
+ { | |
+ m_comparer = Matchers[ComparisonType.AndNot]; | |
+ StrValue = value; | |
+ } | |
+ } | |
+ | |
+ #endregion | |
+ | |
+ /// <summary> | |
+ /// The first (and maybe only) supplied value | |
+ /// </summary> | |
+ [XmlIgnore] | |
+ public string StrValue { get; private set; } | |
+ | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ [XmlElement("Switch", typeof(SwitchPacketSegment), Order = 8)] | |
+ [XmlElement("StaticList", typeof(StaticListPacketSegment), Order = 8)] | |
+ [XmlElement("List", typeof(ListPacketSegment), Order = 8)] | |
+ [XmlElement("Simple", typeof(SimplePacketSegment), Order = 8)] | |
+ public List<XmlPacketSegment> Elements; | |
+ | |
+ /// <summary> | |
+ /// Implements <see cref="IXmlPacketSegmentContainer.ContainedSegments"/>. | |
+ /// </summary> | |
+ /// <returns>The list of packet segments of the current list segment.</returns> | |
+ [XmlIgnore] | |
+ public List<XmlPacketSegment> ContainedSegments | |
+ { | |
+ get { return Elements; } | |
+ } | |
+ } | |
+} | |
\ No newline at end of file | |
diff --git a/PacketViewer/Parsers/XML/Packet Segments/SwitchPacketSegment.cs b/PacketViewer/Parsers/XML/Packet Segments/SwitchPacketSegment.cs | |
new file mode 100644 | |
index 0000000..a471385 | |
--- /dev/null | |
+++ b/PacketViewer/Parsers/XML/Packet Segments/SwitchPacketSegment.cs | |
@@ -0,0 +1,133 @@ | |
+using System; | |
+using System.Collections.Generic; | |
+using System.IO; | |
+using System.Text; | |
+using System.Xml.Serialization; | |
+using Kamilla; | |
+ | |
+namespace PacketViewer.Parsers.XML | |
+{ | |
+ /// <summary> | |
+ /// A PacketSegmentStructure-wrapper whose content decides a switch in another segment of the packet | |
+ /// </summary> | |
+ public class SwitchPacketSegment : SimplePacketSegment, IXmlPacketSegmentContainer | |
+ { | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ public SwitchPacketSegment() | |
+ { | |
+ Cases = new List<SwitchCase>(); | |
+ } | |
+ | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ [XmlAttribute("CompareWith")] | |
+ public string ReferenceName { get; set; } | |
+ | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ [XmlElement("Case", typeof(SwitchCase), Order = 1)] | |
+ public List<SwitchCase> Cases { get; set; } | |
+ | |
+ /// <summary> | |
+ /// | |
+ /// </summary> | |
+ /// <param name="Reader"></param> | |
+ /// <param name="Container"></param> | |
+ /// <returns></returns> | |
+ public override string Parse(BinaryReader Reader, IXmlPacketSegmentContainer Container) | |
+ { | |
+ StringBuilder content = new StringBuilder(); | |
+ List<XmlPacketSegment> parseSegment = new List<XmlPacketSegment>(); | |
+ | |
+ foreach (XmlPacketSegment elem in Container.ContainedSegments) | |
+ { | |
+ if (elem.SegmentName == ReferenceName) | |
+ { | |
+ foreach (SwitchCase condition in Cases) | |
+ { | |
+ Type T = GetType(elem); | |
+ | |
+ if (T != null) | |
+ { | |
+ object sv = GetValue(condition.StrValue, T); | |
+ object cv = GetValue(elem.Value, T); | |
+ | |
+ bool mathes = condition.Matches(cv, sv); | |
+ | |
+ if (mathes) | |
+ { | |
+ content.AppendFormatLine("Case of: {0}", ReferenceName); | |
+ content.AppendLine(condition.Parse(Reader, Container)); | |
+ } | |
+ } | |
+ } | |
+ } | |
+ } | |
+ | |
+ return content.ToString(); | |
+ } | |
+ | |
+ /// <summary> | |
+ /// The type in which values should be converted after parsing (should be an enum) | |
+ /// </summary> | |
+ private Type GetType(XmlPacketSegment segment) | |
+ { | |
+ Type T = Type.GetType("Kamilla.WorldOfWarcraft." + segment.EnumName + ", Kamilla.WorldOfWarcraft"); | |
+ | |
+ if (T == null) | |
+ T = Type.GetType("System." + segment.SimpleType); | |
+ | |
+ if (T == null) | |
+ T = Type.GetType("Kamilla.WorldOfWarcraft." + segment.SimpleType + ", Kamilla.WorldOfWarcraft"); | |
+ | |
+ if (T == null) | |
+ throw new Exception("Filed type: " + segment.SimpleType + ", or enum: " + segment.EnumName); | |
+ | |
+ return T; | |
+ } | |
+ | |
+ private object GetValue(object value, Type T) | |
+ { | |
+ if (T == null || value == null) | |
+ throw new ArgumentNullException(); | |
+ | |
+ try | |
+ { | |
+ if (T.IsEnum) | |
+ return Enum.Parse(T, value.ToString()); | |
+ | |
+ return Convert.ChangeType(value, T); | |
+ } | |
+ catch | |
+ { | |
+ throw new Exception("Parsed: " + value + " of type: " + T.Name); | |
+ } | |
+ } | |
+ | |
+ /// <summary> | |
+ /// Represents a list of packet segments of different complexity. | |
+ /// </summary> | |
+ /* | |
+ [XmlElement("FinalList", typeof(FinalListPacketSegment), Order = 4)] | |
+ */ | |
+ [XmlElement("Switch", typeof(SwitchPacketSegment), Order = 5)] | |
+ [XmlElement("StaticList", typeof(StaticListPacketSegment), Order = 5)] | |
+ [XmlElement("List", typeof(ListPacketSegment), Order = 5)] | |
+ [XmlElement("Simple", typeof(SimplePacketSegment), Order = 5)] | |
+ public List<XmlPacketSegment> Elements; | |
+ | |
+ /// <summary> | |
+ /// Implements <see cref="IXmlPacketSegmentContainer.ContainedSegments"/>. | |
+ /// </summary> | |
+ /// <returns>The list of packet segments of the current list segment.</returns> | |
+ [XmlIgnore] | |
+ public List<XmlPacketSegment> ContainedSegments | |
+ { | |
+ get { return Elements; } | |
+ } | |
+ } | |
+} | |
\ No newline at end of file | |
diff --git a/PacketViewer/Parsers/XML/XmlPacketDefinitions.cs b/PacketViewer/Parsers/XML/XmlPacketDefinitions.cs | |
index 944c346..bb40b99 100644 | |
--- a/PacketViewer/Parsers/XML/XmlPacketDefinitions.cs | |
+++ b/PacketViewer/Parsers/XML/XmlPacketDefinitions.cs | |
@@ -36,25 +36,25 @@ namespace PacketViewer.Parsers.XML | |
/// The Segment's name, displayed to the viewer. | |
/// </summary> | |
[XmlElement("Name", Order = 1)] | |
- public string SegmentName; | |
+ public string SegmentName { get; set; } | |
/// <summary> | |
/// The Segment's data storing type. | |
/// </summary> | |
[XmlElement("Type", Order = 2)] | |
- public XmlTypes SimpleType; | |
+ public XmlTypes SimpleType { get; set; } | |
/// <summary> | |
/// The enum name this Segment represents. | |
/// </summary> | |
[XmlElement("SegmentType", Order = 3)] | |
- public string EnumName; | |
+ public string EnumName { get; set; } | |
/// <summary> | |
/// The parsed value, represented by a string. | |
/// </summary> | |
[XmlIgnore] | |
- public string Value = null; | |
+ public object Value { get; set; } | |
/// <summary> | |
/// Generic parsing method, that must be | |
@@ -79,7 +79,8 @@ namespace PacketViewer.Parsers.XML | |
/// The list of packet segments containted in the current | |
/// implementation of IXmlPacketSegmentContainer. | |
/// </returns> | |
- List<XmlPacketSegment> GetContainedSegments(); | |
+ [XmlIgnore] | |
+ List<XmlPacketSegment> ContainedSegments { get; } | |
} | |
/// <summary> | |
@@ -113,18 +114,22 @@ namespace PacketViewer.Parsers.XML | |
/// </summary> | |
/* | |
[XmlElement("FinalList", typeof(FinalListPacketSegment), Order = 2)] | |
- [XmlElement("Switch", typeof(SwitchPacketSegment), Order = 2)] | |
- */ | |
- [XmlElement("StaticList", typeof(StaticListPacketSegment), Order = 2)] | |
- [XmlElement("List", typeof(ListPacketSegment), Order = 2)] | |
- [XmlElement("Simple", typeof(SimplePacketSegment), Order = 2)] | |
+ */ | |
+ [XmlElement("Switch", typeof(SwitchPacketSegment), Order = 2)] | |
+ [XmlElement("StaticList", typeof(StaticListPacketSegment), Order = 2)] | |
+ [XmlElement("List", typeof(ListPacketSegment), Order = 2)] | |
+ [XmlElement("Simple", typeof(SimplePacketSegment), Order = 2)] | |
public List<XmlPacketSegment> Structure; | |
/// <summary> | |
- /// Implements <see cref="IXmlPacketSegmentContainer.GetContainedSegments"/>. | |
+ /// Implements <see cref="IXmlPacketSegmentContainer.ContainedSegments"/>. | |
/// </summary> | |
/// <returns>The list of packet segments of the current packet definition.</returns> | |
- public List<XmlPacketSegment> GetContainedSegments() { return Structure; } | |
+ [XmlIgnore] | |
+ public List<XmlPacketSegment> ContainedSegments | |
+ { | |
+ get { return Structure; } | |
+ } | |
/// <summary> | |
/// Contains packet sender or Any. | |
diff --git a/PacketViewer/Parsers/XML/XmlParser.cs b/PacketViewer/Parsers/XML/XmlParser.cs | |
index 6d92e95..54e3d2b 100644 | |
--- a/PacketViewer/Parsers/XML/XmlParser.cs | |
+++ b/PacketViewer/Parsers/XML/XmlParser.cs | |
@@ -24,9 +24,10 @@ namespace PacketViewer.Parsers.XML | |
string path = Path.Combine(Application.StartupPath, "Packets"); | |
foreach (string file in Directory.GetFiles(path, "*.xml", SearchOption.AllDirectories)) | |
{ | |
- XmlSerializer deserializer = new XmlSerializer(typeof(XmlPacketDefinitions)); | |
- TextReader textReader = new StreamReader(file); | |
- XmlPacketDefinitions defs = (XmlPacketDefinitions)deserializer.Deserialize(textReader); | |
+ XmlSerializer deserializer = new XmlSerializer(typeof(XmlPacketDefinitions)); | |
+ TextReader textReader = new StreamReader(file); | |
+ XmlPacketDefinitions defs = (XmlPacketDefinitions)deserializer.Deserialize(textReader); | |
+ | |
textReader.Close(); | |
foreach (XmlPacketDefinition def in defs.Definitions) | |
@@ -36,7 +37,7 @@ namespace PacketViewer.Parsers.XML | |
if (def.Opcode != WowOpcodes.MSG_NULL_ACTION && def.Opcode != WowOpcodes.UNKNOWN_OPCODE) | |
{ | |
if (Definitions[def.Sender].ContainsKey(def.Opcode)) | |
- MessageBox.Show(String.Format("XML: double opcode definition for (sender={0} opcode={1})", | |
+ MessageBox.Show(string.Format("XML: double opcode definition for (sender={0} opcode={1})", | |
def.Sender, def.Opcode)); | |
else | |
Definitions[def.Sender].Add(def.Opcode, def); | |
diff --git a/PacketViewer/Parsers/XML/XmlTypeReader.cs b/PacketViewer/Parsers/XML/XmlTypeReader.cs | |
index c24687f..d7c8ade 100644 | |
--- a/PacketViewer/Parsers/XML/XmlTypeReader.cs | |
+++ b/PacketViewer/Parsers/XML/XmlTypeReader.cs | |
@@ -9,6 +9,7 @@ using Kamilla.WorldOfWarcraft; | |
namespace PacketViewer.Parsers.XML | |
{ | |
#pragma warning disable 1591 | |
+ | |
public enum XmlTypes | |
{ | |
None = 0, | |
@@ -61,6 +62,7 @@ namespace PacketViewer.Parsers.XML | |
TimeSpanUntil, | |
TimeSpanMinutesUntil, | |
} | |
+ | |
#pragma warning restore 1591 | |
static class XmlTypeReader | |
@@ -78,40 +80,50 @@ namespace PacketViewer.Parsers.XML | |
static XmlTypeReader() | |
{ | |
- RegisterReader(XmlTypes.Byte, (x) => x.ReadByte().ToString(CultureInfo.InvariantCulture)); | |
- RegisterReader(XmlTypes.SByte, (x) => x.ReadSByte().ToString(CultureInfo.InvariantCulture)); | |
- RegisterReader(XmlTypes.Short, (x) => x.ReadInt16().ToString(CultureInfo.InvariantCulture)); | |
- RegisterReader(XmlTypes.UShort, (x) => x.ReadUInt16().ToString(CultureInfo.InvariantCulture)); | |
- RegisterReader(XmlTypes.Int, (x) => x.ReadInt32().ToString(CultureInfo.InvariantCulture)); | |
- RegisterReader(XmlTypes.UInt, (x) => x.ReadUInt32().ToString(CultureInfo.InvariantCulture)); | |
- RegisterReader(XmlTypes.Long, (x) => x.ReadInt64().ToString(CultureInfo.InvariantCulture)); | |
- RegisterReader(XmlTypes.ULong, (x) => x.ReadUInt64().ToString(CultureInfo.InvariantCulture)); | |
- RegisterReader(XmlTypes.Float, (x) => x.ReadSingle().ToString(CultureInfo.InvariantCulture)); | |
- | |
- RegisterReader(XmlTypes.Vector3, (x) => x.ReadVector3().ToString(CultureInfo.InvariantCulture)); | |
- RegisterReader(XmlTypes.Vector4, (x) => x.ReadVector4().ToString(CultureInfo.InvariantCulture)); | |
- | |
- RegisterReader(XmlTypes.Guid, (x) => x.ReadGuid().ToString()); | |
- RegisterReader(XmlTypes.PackedGuid, (x) => x.ReadPackedGuid().ToString()); | |
- RegisterReader(XmlTypes.PackedValue,(x) => x.ReadPackedGuid().Raw.ToString()); | |
- RegisterReader(XmlTypes.CString, (x) => x.ReadCString().ToString(CultureInfo.InvariantCulture)); | |
- | |
- Func<BinaryReader, int, String> LengthedStringReader = (x, y) => Encoding.UTF8.GetString(x.ReadBytes(y)); | |
- RegisterReader(XmlTypes.PascalStringByte, (x) => LengthedStringReader(x, x.ReadByte())); | |
- RegisterReader(XmlTypes.PascalStringUShort, (x) => LengthedStringReader(x, x.ReadUInt16())); | |
- RegisterReader(XmlTypes.PascalStringUInt, (x) => LengthedStringReader(x, (int)x.ReadUInt32())); | |
- | |
- RegisterReader(XmlTypes.PackedDate, (x) => x.ReadUInt32().AsTimeBitFields().ToString()); | |
- RegisterReader(XmlTypes.UnixTime, (x) => x.ReadUInt32().AsUnixTime().ToString()); | |
- | |
- Func<int, String> TimeSpanFormatter = seconds => new TimeSpan(0, 0, 0, seconds) + " (" + seconds + " seconds)"; | |
- Func<int, String> UntilFormatter = seconds => DateTime.Now.AddSeconds((double)seconds).ToString(); | |
- Func<int, String> TimeSpanUntilFormatter = secs => TimeSpanFormatter(secs) + " (until " + UntilFormatter(secs) + ")"; | |
- | |
- RegisterReader(XmlTypes.TimeSpan, (x) => TimeSpanFormatter(x.ReadInt32())); | |
- RegisterReader(XmlTypes.TimeSpanMinutes, (x) => TimeSpanFormatter(x.ReadInt32()*60)); | |
- RegisterReader(XmlTypes.TimeSpanUntil, (x) => TimeSpanUntilFormatter(x.ReadInt32())); | |
- RegisterReader(XmlTypes.TimeSpanMinutesUntil, (x) => TimeSpanUntilFormatter(x.ReadInt32()*60)); | |
+ Func<BinaryReader, int, String> LengthedStringReader = (x, y) => Encoding.UTF8.GetString(x.ReadBytes(y)); | |
+ Func<int, String> TimeSpanFormatter = seconds => new TimeSpan(0, 0, 0, seconds) + " (" + seconds + " seconds)"; | |
+ Func<int, String> UntilFormatter = seconds => DateTime.Now.AddSeconds((double)seconds).ToString(); | |
+ Func<int, String> TimeSpanUntilFormatter = seconds => TimeSpanFormatter(seconds) + " (until " + UntilFormatter(seconds) + ")"; | |
+ | |
+ #region Readers | |
+ | |
+ // base types | |
+ RegisterReader(XmlTypes.Byte, (x) => x.ReadByte() .ToString(CultureInfo.InvariantCulture)); | |
+ RegisterReader(XmlTypes.SByte, (x) => x.ReadSByte() .ToString(CultureInfo.InvariantCulture)); | |
+ RegisterReader(XmlTypes.Short, (x) => x.ReadInt16() .ToString(CultureInfo.InvariantCulture)); | |
+ RegisterReader(XmlTypes.UShort, (x) => x.ReadUInt16() .ToString(CultureInfo.InvariantCulture)); | |
+ RegisterReader(XmlTypes.Int, (x) => x.ReadInt32() .ToString(CultureInfo.InvariantCulture)); | |
+ RegisterReader(XmlTypes.UInt, (x) => x.ReadUInt32() .ToString(CultureInfo.InvariantCulture)); | |
+ RegisterReader(XmlTypes.Long, (x) => x.ReadInt64() .ToString(CultureInfo.InvariantCulture)); | |
+ RegisterReader(XmlTypes.ULong, (x) => x.ReadUInt64() .ToString(CultureInfo.InvariantCulture)); | |
+ RegisterReader(XmlTypes.Float, (x) => x.ReadSingle() .ToString(CultureInfo.InvariantCulture)); | |
+ | |
+ // wow types | |
+ RegisterReader(XmlTypes.Vector3, (x) => x.ReadVector3().ToString(CultureInfo.InvariantCulture)); | |
+ RegisterReader(XmlTypes.Vector4, (x) => x.ReadVector4().ToString(CultureInfo.InvariantCulture)); | |
+ | |
+ // wow guid | |
+ RegisterReader(XmlTypes.Guid, (x) => x.ReadGuid() .ToString()); | |
+ RegisterReader(XmlTypes.PackedGuid, (x) => x.ReadPackedGuid().ToString()); | |
+ | |
+ // wow packed value | |
+ RegisterReader(XmlTypes.PackedValue, (x) => x.ReadPackedGuid().Raw.ToString()); | |
+ | |
+ // string value | |
+ RegisterReader(XmlTypes.CString, (x) => x.ReadCString().ToString(CultureInfo.InvariantCulture)); | |
+ RegisterReader(XmlTypes.PascalStringByte, (x) => LengthedStringReader(x, x.ReadByte())); | |
+ RegisterReader(XmlTypes.PascalStringUShort, (x) => LengthedStringReader(x, x.ReadUInt16())); | |
+ RegisterReader(XmlTypes.PascalStringUInt, (x) => LengthedStringReader(x, (int)x.ReadUInt32())); | |
+ | |
+ // date value | |
+ RegisterReader(XmlTypes.PackedDate, (x) => x.ReadUInt32().AsTimeBitFields().ToString()); | |
+ RegisterReader(XmlTypes.UnixTime, (x) => x.ReadUInt32().AsUnixTime().ToString()); | |
+ RegisterReader(XmlTypes.TimeSpan, (x) => TimeSpanFormatter(x.ReadInt32())); | |
+ RegisterReader(XmlTypes.TimeSpanMinutes, (x) => TimeSpanFormatter(x.ReadInt32() * 60)); | |
+ RegisterReader(XmlTypes.TimeSpanUntil, (x) => TimeSpanUntilFormatter(x.ReadInt32())); | |
+ RegisterReader(XmlTypes.TimeSpanMinutesUntil, (x) => TimeSpanUntilFormatter(x.ReadInt32() * 60)); | |
+ | |
+ #endregion | |
} | |
public static string Read(BinaryReader reader, XmlTypes type) | |
-- | |
1.7.0.2 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment