/*
Copyright (C) 2014-2019 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see .
*/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using VSUTIL = Microsoft.VisualStudio.Utilities;
namespace dnSpy.Contracts.Hex.Files {
///
/// A file in a
///
public abstract class HexBufferFile : VSUTIL.IPropertyOwner {
///
/// Constructor
///
/// Buffer
/// Span of file
/// Name
/// Filename if possible, otherwise any name
/// Tags, see eg.
protected HexBufferFile(HexBuffer buffer, HexSpan span, string name, string filename, string[] tags) {
if (tags is null)
throw new ArgumentNullException(nameof(tags));
Buffer = buffer ?? throw new ArgumentNullException(nameof(buffer));
Span = span;
Name = name ?? throw new ArgumentNullException(nameof(name));
Filename = filename ?? throw new ArgumentNullException(nameof(filename));
Tags = new ReadOnlyCollection(tags.ToArray());
Properties = new VSUTIL.PropertyCollection();
}
///
/// Gets the properties
///
public VSUTIL.PropertyCollection Properties { get; }
///
/// Gets the buffer
///
public HexBuffer Buffer { get; }
///
/// Gets the file span
///
public HexSpan Span { get; }
///
/// Gets the name
///
public string Name { get; }
///
/// Gets the filename if possible, otherwise it could be any name
///
public string Filename { get; }
///
/// Gets all the tags, see eg.
///
public ReadOnlyCollection Tags { get; }
///
/// Parent file or null if it's not a nested file
///
public abstract HexBufferFile? ParentFile { get; }
///
/// true if it's a nested file ( is not null)
///
public bool IsNestedFile => ParentFile is not null;
///
/// Gets all nested files
///
public abstract IEnumerable Files { get; }
///
/// Creates a file. Overlapping files isn't supported.
///
/// Span of file
///
public HexBufferFile CreateFile(HexSpan span) =>
CreateFiles(new BufferFileOptions(span, string.Empty, string.Empty, Array.Empty())).Single();
///
/// Creates a file. Overlapping files isn't supported.
///
/// Span of file
/// Name
/// Filename if possible, otherwise any name
/// Tags, see eg.
///
public HexBufferFile CreateFile(HexSpan span, string name, string filename, string[] tags) =>
CreateFiles(new BufferFileOptions(span, name, filename, tags)).Single();
///
/// Creates files. Overlapping files isn't supported.
///
/// File options
///
public abstract HexBufferFile[] CreateFiles(params BufferFileOptions[] options);
///
/// Raised after files are added
///
public abstract event EventHandler? BufferFilesAdded;
///
/// Finds a file
///
/// Position
/// true to check nested files
///
public abstract HexBufferFile? GetFile(HexPosition position, bool checkNestedFiles);
///
/// true if it has been removed
///
public abstract bool IsRemoved { get; }
///
/// Raised after it is removed
///
public abstract event EventHandler? Removed;
///
/// Gets a structure
///
/// Position
/// true to check nested files, false to only check this file
///
public ComplexData? GetStructure(HexPosition position, bool checkNestedFiles = true) =>
GetFileAndStructure(position, checkNestedFiles)?.Structure;
///
/// Gets a structure
///
/// Position
/// true to check nested files, false to only check this file
///
public abstract FileAndStructure? GetFileAndStructure(HexPosition position, bool checkNestedFiles = true);
///
/// Gets a structure. Nested files aren't checked.
///
/// Id, see eg.
///
public abstract ComplexData? GetStructure(string id);
///
/// true if has been raised
///
public abstract bool IsStructuresInitialized { get; }
///
/// Raised after the default structures have been added
///
public abstract event EventHandler? StructuresInitialized;
///
/// Gets headers. Nested files aren't checked.
///
/// Type
///
public abstract THeaders? GetHeaders() where THeaders : class, IBufferFileHeaders;
///
/// Aligns up. The returned position is aligned relative to the
/// start of the file, not relative to buffer position 0. I.e., if the file starts at position
/// 2, is 3 and is 4, the returned
/// value is 6, not 4.
///
/// Position
/// Alignment, must be a power of 2
///
public HexPosition AlignUp(HexPosition position, uint alignment) {
if (!Span.Contains(position))
throw new ArgumentOutOfRangeException(nameof(position));
if (!IsPowerOfTwo(alignment))
throw new ArgumentOutOfRangeException(nameof(alignment));
return Span.Start + (((position - Span.Start).ToUInt64() + alignment - 1) & ~(alignment - 1UL));
}
static bool IsPowerOfTwo(uint v) => v != 0 && (v & (v - 1)) == 0;
}
}