/// <summary> /// Creates one or more FormatDescriptor entries for the specified range, adding them /// to the Results list. /// /// This will either create one entry that spans the entire range (for e.g. strings /// and bulk data), or create equal-sized chunks. /// </summary> /// <param name="type">Region data type.</param> /// <param name="subType">Region data sub-type.</param> /// <param name="chunkLength">Length of a chunk, or -1 for full buffer.</param> /// <param name="symbolRef">Symbol reference, or null if not applicable.</param> /// <param name="low">Offset of first byte in range.</param> /// <param name="high">Offset of last byte in range.</param> private void CreateSimpleEntries(FormatDescriptor.Type type, FormatDescriptor.SubType subType, int chunkLength, WeakSymbolRef symbolRef, int low, int high) { if (chunkLength == -1) { chunkLength = (high - low) + 1; } Debug.Assert(((high - low + 1) / chunkLength) * chunkLength == high - low + 1); // Either we have one chunk, or we have multiple chunks with the same type and // length. Either way, we only need to create the descriptor once. (This is // safe because FormatDescriptor instances are immutable.) // // Because certain details, like the fill byte and high-vs-low ASCII, are pulled // out of the data stream at format time, we don't have to dig for them now. FormatDescriptor dfd; if (subType == FormatDescriptor.SubType.Symbol) { dfd = FormatDescriptor.Create(chunkLength, symbolRef, type == FormatDescriptor.Type.NumericBE); } else { dfd = FormatDescriptor.Create(chunkLength, type, subType); } while (low <= high) { Results.Add(low, dfd); low += chunkLength; } }
/// <summary> /// Creates a list of FormatDescriptors, based on the current control configuration. /// /// The entries in the list are guaranteed to be sorted by start address and not /// overlap. /// /// We assume that whatever the control gives us is correct, e.g. it's not going /// to tell us to put a buffer full of zeroes into a DCI string. /// </summary> /// <returns>Result list.</returns> private void CreateDescriptorListFromControls() { FormatDescriptor.Type type = FormatDescriptor.Type.Default; FormatDescriptor.SubType subType = FormatDescriptor.SubType.None; WeakSymbolRef symbolRef = null; int chunkLength = -1; // Decode the "display as" panel, if it's relevant. if (radioSimpleDataHex.Enabled) { if (radioSimpleDataHex.Checked) { subType = FormatDescriptor.SubType.Hex; } else if (radioSimpleDataDecimal.Checked) { subType = FormatDescriptor.SubType.Decimal; } else if (radioSimpleDataBinary.Checked) { subType = FormatDescriptor.SubType.Binary; } else if (radioSimpleDataAscii.Checked) { subType = FormatDescriptor.SubType.Ascii; } else if (radioSimpleDataAddress.Checked) { subType = FormatDescriptor.SubType.Address; } else if (radioSimpleDataSymbolic.Checked) { WeakSymbolRef.Part part; if (radioSymbolPartLow.Checked) { part = WeakSymbolRef.Part.Low; } else if (radioSymbolPartHigh.Checked) { part = WeakSymbolRef.Part.High; } else if (radioSymbolPartBank.Checked) { part = WeakSymbolRef.Part.Bank; } else { Debug.Assert(false); part = WeakSymbolRef.Part.Low; } subType = FormatDescriptor.SubType.Symbol; symbolRef = new WeakSymbolRef(symbolEntryTextBox.Text, part); } else { Debug.Assert(false); } } else { subType = 0; // set later, or doesn't matter } // Decode the main format. if (radioDefaultFormat.Checked) { // Default/None; note this would create a multi-byte Default format, which isn't // really allowed. What we actually want to do is remove the explicit formatting // from all spanned offsets, so we use a dedicated type for that. type = FormatDescriptor.Type.REMOVE; } else if (radioSingleBytes.Checked) { type = FormatDescriptor.Type.NumericLE; chunkLength = 1; } else if (radio16BitLittle.Checked) { type = FormatDescriptor.Type.NumericLE; chunkLength = 2; } else if (radio16BitBig.Checked) { type = FormatDescriptor.Type.NumericBE; chunkLength = 2; } else if (radio24BitLittle.Checked) { type = FormatDescriptor.Type.NumericLE; chunkLength = 3; } else if (radio32BitLittle.Checked) { type = FormatDescriptor.Type.NumericLE; chunkLength = 4; } else if (radioDenseHex.Checked) { type = FormatDescriptor.Type.Dense; } else if (radioFill.Checked) { type = FormatDescriptor.Type.Fill; } else if (radioStringMixed.Checked) { type = FormatDescriptor.Type.String; } else if (radioStringMixedReverse.Checked) { type = FormatDescriptor.Type.String; subType = FormatDescriptor.SubType.Reverse; } else if (radioStringNullTerm.Checked) { type = FormatDescriptor.Type.String; subType = FormatDescriptor.SubType.CString; } else if (radioStringLen8.Checked) { type = FormatDescriptor.Type.String; subType = FormatDescriptor.SubType.L8String; } else if (radioStringLen16.Checked) { type = FormatDescriptor.Type.String; subType = FormatDescriptor.SubType.L16String; } else if (radioStringDci.Checked) { type = FormatDescriptor.Type.String; subType = FormatDescriptor.SubType.Dci; //} else if (radioStringDciReverse.Checked) { // type = FormatDescriptor.Type.String; // subType = FormatDescriptor.SubType.DciReverse; } else { Debug.Assert(false); // default/none } Results = new SortedList <int, FormatDescriptor>(); IEnumerator <TypedRangeSet.TypedRange> iter = Selection.RangeListIterator; while (iter.MoveNext()) { TypedRangeSet.TypedRange rng = iter.Current; if (type == FormatDescriptor.Type.String) { // We want to create one FormatDescriptor object per string. That way // each string gets its own line. if ((subType == FormatDescriptor.SubType.None || subType == FormatDescriptor.SubType.Reverse)) { CreateMixedStringEntries(rng.Low, rng.High, subType); } else if (subType == FormatDescriptor.SubType.CString) { CreateCStringEntries(rng.Low, rng.High, subType); } else if (subType == FormatDescriptor.SubType.L8String || subType == FormatDescriptor.SubType.L16String) { CreateLengthStringEntries(rng.Low, rng.High, subType); } else if (subType == FormatDescriptor.SubType.Dci || subType == FormatDescriptor.SubType.DciReverse) { CreateDciStringEntries(rng.Low, rng.High, subType); } else { Debug.Assert(false); CreateMixedStringEntries(rng.Low, rng.High, subType); // shrug } } else { CreateSimpleEntries(type, subType, chunkLength, symbolRef, rng.Low, rng.High); } } }