using System.Collections.Generic; using System.IO; using System.Text; namespace PriFileFormat { public class DecisionInfoSection: Section { public IReadOnlyList Decisions { get; private set; } public IReadOnlyList QualifierSets { get; private set; } public IReadOnlyList Qualifiers { get; private set; } internal const string Identifier = "[mrm_decn_info]\0"; internal DecisionInfoSection (PriFile priFile) : base (Identifier, priFile) {} protected override bool ParseSectionContent (BinaryReader binaryReader) { ushort numDistinctQualifiers = binaryReader.ReadUInt16 (); ushort numQualifiers = binaryReader.ReadUInt16 (); ushort numQualifierSets = binaryReader.ReadUInt16 (); ushort numDecisions = binaryReader.ReadUInt16 (); ushort numIndexTableEntries = binaryReader.ReadUInt16 (); ushort totalDataLength = binaryReader.ReadUInt16 (); List decisionInfos = new List (numDecisions); for (int i = 0; i < numDecisions; i++) { ushort firstQualifierSetIndexIndex = binaryReader.ReadUInt16 (); ushort numQualifierSetsInDecision = binaryReader.ReadUInt16 (); decisionInfos.Add (new DecisionInfo (firstQualifierSetIndexIndex, numQualifierSetsInDecision)); } List qualifierSetInfos = new List (numQualifierSets); for (int i = 0; i < numQualifierSets; i++) { ushort firstQualifierIndexIndex = binaryReader.ReadUInt16 (); ushort numQualifiersInSet = binaryReader.ReadUInt16 (); qualifierSetInfos.Add (new QualifierSetInfo (firstQualifierIndexIndex, numQualifiersInSet)); } List qualifierInfos = new List (numQualifiers); for (int i = 0; i < numQualifiers; i++) { ushort index = binaryReader.ReadUInt16 (); ushort priority = binaryReader.ReadUInt16 (); ushort fallbackScore = binaryReader.ReadUInt16 (); binaryReader.ExpectUInt16 (0); qualifierInfos.Add (new QualifierInfo (index, priority, fallbackScore)); } List distinctQualifierInfos = new List (numDistinctQualifiers); for (int i = 0; i < numDistinctQualifiers; i++) { binaryReader.ReadUInt16 (); QualifierType qualifierType = (QualifierType)binaryReader.ReadUInt16 (); binaryReader.ReadUInt16 (); binaryReader.ReadUInt16 (); uint operandValueOffset = binaryReader.ReadUInt32 (); distinctQualifierInfos.Add (new DistinctQualifierInfo (qualifierType, operandValueOffset)); } ushort [] indexTable = new ushort [numIndexTableEntries]; for (int i = 0; i < numIndexTableEntries; i++) indexTable [i] = binaryReader.ReadUInt16 (); long dataStartOffset = binaryReader.BaseStream.Position; List qualifiers = new List (numQualifiers); for (int i = 0; i < numQualifiers; i++) { DistinctQualifierInfo distinctQualifierInfo = distinctQualifierInfos [qualifierInfos [i].Index]; binaryReader.BaseStream.Seek (dataStartOffset + distinctQualifierInfo.OperandValueOffset * 2, SeekOrigin.Begin); string value = binaryReader.ReadNullTerminatedString (Encoding.Unicode); qualifiers.Add (new Qualifier ( (ushort)i, distinctQualifierInfo.QualifierType, qualifierInfos [i].Priority, qualifierInfos [i].FallbackScore / 1000f, value)); } Qualifiers = qualifiers; List qualifierSets = new List (numQualifierSets); for (int i = 0; i < numQualifierSets; i++) { List qualifiersInSet = new List (qualifierSetInfos [i].NumQualifiersInSet); for (int j = 0; j < qualifierSetInfos [i].NumQualifiersInSet; j++) qualifiersInSet.Add (qualifiers [indexTable [qualifierSetInfos [i].FirstQualifierIndexIndex + j]]); qualifierSets.Add (new QualifierSet ((ushort)i, qualifiersInSet)); } QualifierSets = qualifierSets; List decisions = new List (numDecisions); for (int i = 0; i < numDecisions; i++) { List qualifierSetsInDecision = new List (decisionInfos [i].NumQualifierSetsInDecision); for (int j = 0; j < decisionInfos [i].NumQualifierSetsInDecision; j++) qualifierSetsInDecision.Add (qualifierSets [indexTable [decisionInfos [i].FirstQualifierSetIndexIndex + j]]); decisions.Add (new Decision ((ushort)i, qualifierSetsInDecision)); } Decisions = decisions; return true; } private struct DecisionInfo { public ushort FirstQualifierSetIndexIndex; public ushort NumQualifierSetsInDecision; public DecisionInfo (ushort firstQualifierSetIndexIndex, ushort numQualifierSetsInDecision) { FirstQualifierSetIndexIndex = firstQualifierSetIndexIndex; NumQualifierSetsInDecision = numQualifierSetsInDecision; } } private struct QualifierSetInfo { public ushort FirstQualifierIndexIndex; public ushort NumQualifiersInSet; public QualifierSetInfo (ushort firstQualifierIndexIndex, ushort numQualifiersInSet) { FirstQualifierIndexIndex = firstQualifierIndexIndex; NumQualifiersInSet = numQualifiersInSet; } } private struct QualifierInfo { public ushort Index; public ushort Priority; public ushort FallbackScore; public QualifierInfo (ushort index, ushort priority, ushort fallbackScore) { Index = index; Priority = priority; FallbackScore = fallbackScore; } } private struct DistinctQualifierInfo { public QualifierType QualifierType; public uint OperandValueOffset; public DistinctQualifierInfo (QualifierType qualifierType, uint operandValueOffset) { QualifierType = qualifierType; OperandValueOffset = operandValueOffset; } } } public enum QualifierType { Language, Contrast, Scale, HomeRegion, TargetSize, LayoutDirection, Theme, AlternateForm, DXFeatureLevel, Configuration, DeviceFamily, Custom } public class Qualifier { public ushort Index { get; } public QualifierType Type { get; } public ushort Priority { get; } public float FallbackScore { get; } public string Value { get; } internal Qualifier (ushort index, QualifierType type, ushort priority, float fallbackScore, string value) { Index = index; Type = type; Priority = priority; FallbackScore = fallbackScore; Value = value; } public override string ToString () { return $"Index: {Index} Type: {Type} Value: {Value} Priority: {Priority} FallbackScore: {FallbackScore}"; } } public class QualifierSet { public ushort Index { get; } public IReadOnlyList Qualifiers { get; } internal QualifierSet (ushort index, IReadOnlyList qualifiers) { Index = index; Qualifiers = qualifiers; } public override string ToString () { return $"Index: {Index} Qualifiers: {Qualifiers.Count}"; } } public class Decision { public ushort Index { get; } public IReadOnlyList QualifierSets { get; } internal Decision (ushort index, IReadOnlyList qualifierSets) { Index = index; QualifierSets = qualifierSets; } public override string ToString () { return $"Index: {Index} Qualifier sets: {QualifierSets.Count}"; } } }