public override HexBufferLineProvider Create(HexBuffer buffer, HexBufferLineProviderOptions options) {
			if (buffer == null)
				throw new ArgumentNullException(nameof(buffer));
			if (options == null)
				throw new ArgumentNullException(nameof(options));
			return new HexBufferLineProviderImpl(buffer, options);
		}
Пример #2
0
		HexBufferLineProviderOptions GetHexBufferLineProviderOptions() {
			Debug.Assert(!double.IsNaN(lastFormattedLineSourceViewportWidth));
			var options = new HexBufferLineProviderOptions();
			options.CharsPerLine = (int)((lastFormattedLineSourceViewportWidth - FormattedLineSource.BaseIndentation) / FormattedLineSource.ColumnWidth);
			options.BytesPerLine = Options.GetBytesPerLine();
			options.GroupSizeInBytes = Options.GetGroupSizeInBytes();
			options.ShowOffset = Options.ShowOffsetColumn();
			options.OffsetLowerCaseHex = Options.IsOffsetLowerCaseHexEnabled();
			options.OffsetFormat = Options.GetOffsetFormat();
			options.StartPosition = Options.GetStartPosition();
			options.EndPosition = Options.GetEndPosition();
			options.BasePosition = Options.GetBasePosition();
			options.UseRelativePositions = Options.UseRelativePositions();
			options.ShowValues = Options.ShowValuesColumn();
			options.ValuesLowerCaseHex = Options.IsValuesLowerCaseHexEnabled();
			options.OffsetBitSize = Options.GetOffsetBitSize();
			options.ValuesFormat = Options.GetValuesDisplayFormat();
			options.ShowAscii = Options.ShowAsciiColumn();
			options.ColumnOrder = new HexColumnType[3] { HexColumnType.Offset, HexColumnType.Values, HexColumnType.Ascii };

			const int DEFAULT_CHARS_PER_LINE = 80;
			if (options.CharsPerLine <= 0)
				options.CharsPerLine = DEFAULT_CHARS_PER_LINE;
			if (options.BytesPerLine < HexBufferLineProviderOptions.MinBytesPerLine)
				options.BytesPerLine = 0;
			else if (options.BytesPerLine > HexBufferLineProviderOptions.MaxBytesPerLine)
				options.BytesPerLine = HexBufferLineProviderOptions.MaxBytesPerLine;
			if (options.GroupSizeInBytes < 0)
				options.GroupSizeInBytes = 0;
			if (options.StartPosition >= HexPosition.MaxEndPosition)
				options.StartPosition = 0;
			if (options.EndPosition > HexPosition.MaxEndPosition)
				options.EndPosition = HexPosition.MaxEndPosition;
			if (options.StartPosition > options.EndPosition)
				options.StartPosition = options.EndPosition;
			if (options.BasePosition >= HexPosition.MaxEndPosition)
				options.BasePosition = 0;
			if (options.OffsetBitSize < HexBufferLineProviderOptions.MinOffsetBitSize)
				options.OffsetBitSize = HexBufferLineProviderOptions.MinOffsetBitSize;
			else if (options.OffsetBitSize > HexBufferLineProviderOptions.MaxOffsetBitSize)
				options.OffsetBitSize = HexBufferLineProviderOptions.MaxOffsetBitSize;
			if (options.OffsetFormat < HexBufferLineProviderOptions.HexOffsetFormat_First || options.OffsetFormat > HexBufferLineProviderOptions.HexOffsetFormat_Last)
				options.OffsetFormat = HexOffsetFormat.Hex;
			if (options.ValuesFormat < HexBufferLineProviderOptions.HexValuesDisplayFormat_First || options.ValuesFormat > HexBufferLineProviderOptions.HexValuesDisplayFormat_Last)
				options.ValuesFormat = HexValuesDisplayFormat.HexByte;

			return options;
		}
		/// <summary>
		/// Creates a new <see cref="HexBufferLineProvider"/> instance
		/// </summary>
		/// <param name="buffer">Buffer</param>
		/// <param name="options">Options</param>
		/// <returns></returns>
		public abstract HexBufferLineProvider Create(HexBuffer buffer, HexBufferLineProviderOptions options);
		public HexBufferLineProviderImpl(HexBuffer buffer, HexBufferLineProviderOptions options) {
			if (buffer == null)
				throw new ArgumentNullException(nameof(buffer));
			if (options == null)
				throw new ArgumentNullException(nameof(options));
			if (options.CharsPerLine < 0)
				throw new ArgumentOutOfRangeException(nameof(options));
			if (options.BytesPerLine < HexBufferLineProviderOptions.MinBytesPerLine || options.BytesPerLine > HexBufferLineProviderOptions.MaxBytesPerLine)
				throw new ArgumentOutOfRangeException(nameof(options));
			if (options.GroupSizeInBytes < 0)
				throw new ArgumentOutOfRangeException(nameof(options));
			if (options.OffsetFormat < HexBufferLineProviderOptions.HexOffsetFormat_First || options.OffsetFormat > HexBufferLineProviderOptions.HexOffsetFormat_Last)
				throw new ArgumentOutOfRangeException(nameof(options));
			if (options.StartPosition >= HexPosition.MaxEndPosition)
				throw new ArgumentOutOfRangeException(nameof(options));
			if (options.EndPosition > HexPosition.MaxEndPosition)
				throw new ArgumentOutOfRangeException(nameof(options));
			if (options.StartPosition > options.EndPosition)
				throw new ArgumentOutOfRangeException(nameof(options));
			if (options.BasePosition >= HexPosition.MaxEndPosition)
				throw new ArgumentOutOfRangeException(nameof(options));
			if (options.OffsetBitSize < HexBufferLineProviderOptions.MinOffsetBitSize || options.OffsetBitSize > HexBufferLineProviderOptions.MaxOffsetBitSize)
				throw new ArgumentOutOfRangeException(nameof(options));
			if (options.ValuesFormat < HexBufferLineProviderOptions.HexValuesDisplayFormat_First || options.ValuesFormat > HexBufferLineProviderOptions.HexValuesDisplayFormat_Last)
				throw new ArgumentOutOfRangeException(nameof(options));

			this.buffer = buffer;
			columnOrder = TryCreateColumns(options.ColumnOrder ?? defaultColumnOrders);
			if (columnOrder == null)
				throw new ArgumentOutOfRangeException(nameof(options));
			cellList = new List<HexCell>();
			useRelativePositions = options.UseRelativePositions;
			startPosition = options.StartPosition;
			endPosition = options.EndPosition;
			basePosition = options.BasePosition;
			showOffset = options.ShowOffset;
			showValues = options.ShowValues;
			showAscii = options.ShowAscii;
			valuesLowerCaseHex = options.ValuesLowerCaseHex;

			int bitSize = options.OffsetBitSize;
			if (bitSize == 0)
				bitSize = CalculateOffsetBitSize();
			offsetFormatter = CreateOffsetFormatter(options.OffsetFormat, bitSize, options.OffsetLowerCaseHex);
			valueFormatter = valueFormatters[(int)options.ValuesFormat];

			bytesPerLine = (ulong)options.BytesPerLine;
			if (bytesPerLine == 0)
				bytesPerLine = (ulong)CalculateBytesPerLine(options.CharsPerLine);
			if (bytesPerLine % (ulong)valueFormatter.ByteCount != 0)
				bytesPerLine = bytesPerLine - bytesPerLine % (ulong)valueFormatter.ByteCount + (ulong)valueFormatter.ByteCount;
			if (bytesPerLine > (ulong)HexBufferLineProviderOptions.MaxBytesPerLine)
				bytesPerLine = (ulong)(HexBufferLineProviderOptions.MaxBytesPerLine / valueFormatter.ByteCount * valueFormatter.ByteCount);
			if (bytesPerLine <= 0)
				throw new InvalidOperationException();
			groupSizeInBytes = options.GroupSizeInBytes;
			if (groupSizeInBytes == 0)
				groupSizeInBytes = DEFAULT_GROUP_SIZE_IN_BYTES;
			if ((ulong)groupSizeInBytes > bytesPerLine)
				groupSizeInBytes = (int)bytesPerLine;
			groupSizeInBytes = (groupSizeInBytes + valueFormatter.ByteCount - 1) / valueFormatter.ByteCount * valueFormatter.ByteCount;
			if (groupSizeInBytes <= 0)
				throw new InvalidOperationException();
			CharsPerLine = CalculateCharsPerLine();
			stringBuilder = new StringBuilder(CharsPerLine);

			var totalBytes = options.EndPosition - options.StartPosition;
			Debug.Assert(totalBytes <= new HexPosition(1, 0));
			if (totalBytes == 0)
				LineCount = 1;
			else if (bytesPerLine == 1)
				LineCount = totalBytes;
			else if (totalBytes == new HexPosition(1, 0)) {
				// 2^64 / x => (2^64 - x + x) / x => (2^64 - x) / x + 1
				Debug.Assert(bytesPerLine > 1);
				ulong d = (0UL - bytesPerLine) / bytesPerLine + 1UL;
				ulong r = 0UL - (d * bytesPerLine);
				LineCount = d + (r == 0UL ? 0UL : 1UL);
			}
			else {
				ulong v = totalBytes.ToUInt64();
				LineCount = v / bytesPerLine + (v % bytesPerLine == 0 ? 0UL : 1UL);
			}
			if (LineCount == 0)
				throw new InvalidOperationException();

			VST.Span offsetSpan, valuesSpan, asciiSpan;
			CalculateColumnSpans(out offsetSpan, out valuesSpan, out asciiSpan);
			OffsetSpan = offsetSpan;
			ValuesSpan = valuesSpan;
			AsciiSpan = asciiSpan;

			var group = new List<HexGroupInformation>();
			CalculateValuesGroupSpans(group);
			ValuesGroup = new ReadOnlyCollection<HexGroupInformation>(group.ToArray());
			CalculateAsciiGroupSpans(group);
			AsciiGroup = new ReadOnlyCollection<HexGroupInformation>(group.ToArray());
			if (ShowValues == ShowAscii && ValuesGroup.Count != AsciiGroup.Count)
				throw new InvalidOperationException();
		}