Browse Source

sort BamlRecordType; clean up some code; replace Hashtable with Dictionary

pull/182/merge
Siegfried Pammer 14 years ago
parent
commit
1009303088
  1. 4
      ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj
  2. 22
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/BAML format.txt
  3. 117
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/BamlRecordType.cs
  4. 59
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs

4
ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj

@ -14,6 +14,7 @@
<NoStdLib>False</NoStdLib> <NoStdLib>False</NoStdLib>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors> <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'x86' "> <PropertyGroup Condition=" '$(Platform)' == 'x86' ">
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
@ -130,5 +131,8 @@
<Private>False</Private> <Private>False</Private>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="Ricciolo.StylesExplorer.MarkupReflection\BAML format.txt" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
</Project> </Project>

22
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/BAML format.txt

@ -0,0 +1,22 @@
BAML format description
A BAML stream consists of a header and sequential records that contain the data.
The Header
The header is 28 bytes long. The first four bytes are a little endian integer containing the length of the preamble in bytes. The preamble is the UTF-16 string "MSBAML", followed by three integers with the value 0x60000.
Record format:
In general a record consists of a type byte and its content. Some records also have a field, following the type byte, containing the remaining length of the record, encoded as 7-bit encoded integer.
Record Types:
DocumentStart (= 0x01):
The document start (after the type byte) is 6 Bytes long. Usually 00 FF FF FF FF 00. These bytes can be safely ignored.
AssemblyInfo (= 0xC1):
The length field is followed by a 2 byte long ID. The ID is followed by a string containing the assembly name.

117
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/BamlRecordType.cs

@ -9,64 +9,63 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
{ {
internal enum BamlRecordType : byte internal enum BamlRecordType : byte
{ {
AssemblyInfo = 0x1c, Unknown,
AttributeInfo = 0x1f, DocumentStart,
ClrEvent = 0x13, DocumentEnd,
Comment = 0x17, ElementStart,
ConnectionId = 0x2d, ElementEnd,
ConstructorParametersEnd = 0x2b, Property,
ConstructorParametersStart = 0x2a, PropertyCustom,
ConstructorParameterType = 0x2c, PropertyComplexStart,
ContentProperty = 0x2e, PropertyComplexEnd,
DefAttribute = 0x19, PropertyArrayStart,
DefAttributeKeyString = 0x26, PropertyArrayEnd,
DefAttributeKeyType = 0x27, PropertyListStart,
DeferableContentStart = 0x25, PropertyListEnd,
DefTag = 0x18, PropertyDictionaryStart,
DocumentEnd = 2, PropertyDictionaryEnd,
DocumentStart = 1, LiteralContent,
ElementEnd = 4, Text,
ElementStart = 3, TextWithConverter,
EndAttributes = 0x1a, RoutedEvent,
KeyElementEnd = 0x29, ClrEvent,
KeyElementStart = 40, XmlnsProperty,
LastRecordType = 0x39, XmlAttribute,
LineNumberAndPosition = 0x35, ProcessingInstruction,
LinePosition = 0x36, Comment,
LiteralContent = 15, DefTag,
NamedElementStart = 0x2f, DefAttribute,
OptimizedStaticResource = 0x37, EndAttributes,
PIMapping = 0x1b, PIMapping,
PresentationOptionsAttribute = 0x34, AssemblyInfo,
ProcessingInstruction = 0x16, TypeInfo,
Property = 5, TypeSerializerInfo,
PropertyArrayEnd = 10, AttributeInfo,
PropertyArrayStart = 9, StringInfo,
PropertyComplexEnd = 8, PropertyStringReference,
PropertyComplexStart = 7, PropertyTypeReference,
PropertyCustom = 6, PropertyWithExtension,
PropertyDictionaryEnd = 14, PropertyWithConverter,
PropertyDictionaryStart = 13, DeferableContentStart,
PropertyListEnd = 12, DefAttributeKeyString,
PropertyListStart = 11, DefAttributeKeyType,
PropertyStringReference = 0x21, KeyElementStart,
PropertyTypeReference = 0x22, KeyElementEnd,
PropertyWithConverter = 0x24, ConstructorParametersStart,
PropertyWithExtension = 0x23, ConstructorParametersEnd,
PropertyWithStaticResourceId = 0x38, ConstructorParameterType,
RoutedEvent = 0x12, ConnectionId,
StaticResourceEnd = 0x31, ContentProperty,
StaticResourceId = 50, NamedElementStart,
StaticResourceStart = 0x30, StaticResourceStart,
StringInfo = 0x20, StaticResourceEnd,
Text = 0x10, StaticResourceId,
TextWithConverter = 0x11, TextWithId,
TextWithId = 0x33, PresentationOptionsAttribute,
TypeInfo = 0x1d, LineNumberAndPosition,
TypeSerializerInfo = 30, LinePosition,
Unknown = 0, OptimizedStaticResource,
XmlAttribute = 0x15, PropertyWithStaticResourceId,
XmlnsProperty = 20 LastRecordType
} }
} }

59
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs

@ -21,10 +21,10 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
#region Variables #region Variables
private BamlBinaryReader reader; private BamlBinaryReader reader;
private Hashtable assemblyTable = new Hashtable(); private Dictionary<short, string> assemblyTable = new Dictionary<short, string>();
private Hashtable stringTable = new Hashtable(); private Dictionary<short, string> stringTable = new Dictionary<short, string>();
private Hashtable typeTable = new Hashtable(); private Dictionary<short, TypeDeclaration> typeTable = new Dictionary<short, TypeDeclaration>();
private Hashtable propertyTable = new Hashtable(); private Dictionary<short, PropertyDeclaration> propertyTable = new Dictionary<short, PropertyDeclaration>();
private readonly ITypeResolver _resolver; private readonly ITypeResolver _resolver;
@ -247,9 +247,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
{ {
do do
{ {
currentType = (BamlRecordType)reader.ReadByte(); ReadRecordType();
//Debug.WriteLine(currentType); if (currentType == BamlRecordType.DocumentEnd)
if (currentType == BamlRecordType.DocumentEnd) break; break;
long position = reader.BaseStream.Position; long position = reader.BaseStream.Position;
@ -257,9 +257,8 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
ProcessNext(); ProcessNext();
if (bytesToSkip > 0) if (bytesToSkip > 0)
{ // jump to the end of the record
reader.BaseStream.Position = position + bytesToSkip; reader.BaseStream.Position = position + bytesToSkip;
}
} }
//while (currentType != BamlRecordType.DocumentEnd); //while (currentType != BamlRecordType.DocumentEnd);
while (nodes.Count == 0 || (currentType != BamlRecordType.ElementEnd) || complexPropertyOpened > 0); while (nodes.Count == 0 || (currentType != BamlRecordType.ElementEnd) || complexPropertyOpened > 0);
@ -277,6 +276,23 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
} }
} }
void ReadRecordType()
{
byte type = reader.ReadByte();
if (type < 0)
currentType = BamlRecordType.DocumentEnd;
else
currentType = (BamlRecordType)type;
if (currentType.ToString().EndsWith("End"))
Debug.Unindent();
Debug.WriteLine(currentType);
if (currentType.ToString().StartsWith("Start"))
Debug.Indent();
}
private bool SetNextNode() private bool SetNextNode()
{ {
while (nodes.Count > 0) while (nodes.Count > 0)
@ -305,12 +321,8 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
switch (currentType) switch (currentType)
{ {
case BamlRecordType.DocumentStart: case BamlRecordType.DocumentStart:
{ reader.ReadBytes(6);
reader.ReadBoolean(); break;
reader.ReadInt32();
reader.ReadBoolean();
break;
}
case BamlRecordType.DocumentEnd: case BamlRecordType.DocumentEnd:
break; break;
case BamlRecordType.ElementStart: case BamlRecordType.ElementStart:
@ -586,7 +598,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
PropertyDeclaration declaration; PropertyDeclaration declaration;
if (identifier >= 0) if (identifier >= 0)
{ {
declaration = (PropertyDeclaration)this.propertyTable[identifier]; declaration = this.propertyTable[identifier];
} }
else else
{ {
@ -603,7 +615,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
{ {
if (identifier >= 0) if (identifier >= 0)
{ {
PropertyDeclaration declaration = (PropertyDeclaration)this.propertyTable[identifier]; PropertyDeclaration declaration = this.propertyTable[identifier];
return declaration; return declaration;
} }
else else
@ -906,7 +918,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
pd = new PropertyDeclaration("Name", XamlTypeDeclaration); pd = new PropertyDeclaration("Name", XamlTypeDeclaration);
break; break;
default: default:
string recordName = (string)this.stringTable[identifier]; string recordName = this.stringTable[identifier];
if (recordName != "Key") throw new NotSupportedException(recordName); if (recordName != "Key") throw new NotSupportedException(recordName);
pd = new PropertyDeclaration(recordName, XamlTypeDeclaration); pd = new PropertyDeclaration(recordName, XamlTypeDeclaration);
@ -926,7 +938,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
int position = reader.ReadInt32(); int position = reader.ReadInt32();
//bool shared = reader.ReadBoolean(); //bool shared = reader.ReadBoolean();
//bool sharedSet = reader.ReadBoolean(); //bool sharedSet = reader.ReadBoolean();
string text = (string)this.stringTable[num]; string text = this.stringTable[num];
if (text == null) if (text == null)
throw new NotSupportedException(); throw new NotSupportedException();
@ -963,7 +975,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
string[] textArray = new string[(uint)reader.ReadInt16()]; string[] textArray = new string[(uint)reader.ReadInt16()];
for (int i = 0; i < textArray.Length; i++) for (int i = 0; i < textArray.Length; i++)
{ {
textArray[i] = (string)this.assemblyTable[reader.ReadInt16()]; textArray[i] = this.assemblyTable[reader.ReadInt16()];
} }
XmlNamespaceCollection namespaces = elements.Peek().Namespaces; XmlNamespaceCollection namespaces = elements.Peek().Namespaces;
@ -1045,6 +1057,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
private void ReadPropertyComplexEnd() private void ReadPropertyComplexEnd()
{ {
if (!(elements.Peek() is XmlBamlPropertyElement))
throw new InvalidCastException();
XmlBamlPropertyElement propertyElement = (XmlBamlPropertyElement) elements.Peek(); XmlBamlPropertyElement propertyElement = (XmlBamlPropertyElement) elements.Peek();
CloseElement(); CloseElement();
@ -1546,7 +1561,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
{ {
TypeDeclaration declaration; TypeDeclaration declaration;
if (identifier >= 0) if (identifier >= 0)
declaration = (TypeDeclaration)this.typeTable[identifier]; declaration = this.typeTable[identifier];
else else
declaration = KnownInfo.KnownTypeTable[-identifier]; declaration = KnownInfo.KnownTypeTable[-identifier];
@ -1558,7 +1573,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
internal string GetAssembly(short identifier) internal string GetAssembly(short identifier)
{ {
return this.assemblyTable[identifier].ToString(); return this.assemblyTable[identifier];
} }
private XmlBamlNode CurrentNode private XmlBamlNode CurrentNode

Loading…
Cancel
Save