diff --git a/BizHawk.Client.Common/SevenZipSharpArchiveHandler.cs b/BizHawk.Client.Common/SevenZipSharpArchiveHandler.cs index 7d4f951edd..59222db47b 100644 --- a/BizHawk.Client.Common/SevenZipSharpArchiveHandler.cs +++ b/BizHawk.Client.Common/SevenZipSharpArchiveHandler.cs @@ -52,8 +52,8 @@ namespace BizHawk.Client.Common var ai = new HawkFileArchiveItem { - name = HawkFile.Util_FixArchiveFilename(afd.FileName), - size = (long)afd.Size, archiveIndex = i, index = ret.Count + Name = HawkFile.Util_FixArchiveFilename(afd.FileName), + Size = (long)afd.Size, ArchiveIndex = i, Index = ret.Count }; ret.Add(ai); diff --git a/BizHawk.Client.Common/movie/MovieImport.cs b/BizHawk.Client.Common/movie/MovieImport.cs index e65e6c2f7f..f8eebac06d 100644 --- a/BizHawk.Client.Common/movie/MovieImport.cs +++ b/BizHawk.Client.Common/movie/MovieImport.cs @@ -993,9 +993,9 @@ namespace BizHawk.Client.Common string platform = "SNES"; foreach (var item in hf.ArchiveItems) { - if (item.name == "authors") + if (item.Name == "authors") { - hf.BindArchiveMember(item.index); + hf.BindArchiveMember(item.Index); var stream = hf.GetStream(); string authors = Encoding.UTF8.GetString(Util.ReadAllBytes(stream)); string author_list = ""; @@ -1028,25 +1028,25 @@ namespace BizHawk.Client.Common m.Header[HeaderKeys.AUTHOR] = author_list; hf.Unbind(); } - else if (item.name == "coreversion") + else if (item.Name == "coreversion") { - hf.BindArchiveMember(item.index); + hf.BindArchiveMember(item.Index); var stream = hf.GetStream(); string coreversion = Encoding.UTF8.GetString(Util.ReadAllBytes(stream)).Trim(); m.Header.Comments.Add(COREORIGIN + " " + coreversion); hf.Unbind(); } - else if (item.name == "gamename") + else if (item.Name == "gamename") { - hf.BindArchiveMember(item.index); + hf.BindArchiveMember(item.Index); var stream = hf.GetStream(); string gamename = Encoding.UTF8.GetString(Util.ReadAllBytes(stream)).Trim(); m.Header[HeaderKeys.GAMENAME] = gamename; hf.Unbind(); } - else if (item.name == "gametype") + else if (item.Name == "gametype") { - hf.BindArchiveMember(item.index); + hf.BindArchiveMember(item.Index); var stream = hf.GetStream(); string gametype = Encoding.UTF8.GetString(Util.ReadAllBytes(stream)).Trim(); // TODO: Handle the other types. @@ -1069,9 +1069,9 @@ namespace BizHawk.Client.Common m.Header[HeaderKeys.PAL] = pal.ToString(); hf.Unbind(); } - else if (item.name == "input") + else if (item.Name == "input") { - hf.BindArchiveMember(item.index); + hf.BindArchiveMember(item.Index); var stream = hf.GetStream(); string input = Encoding.UTF8.GetString(Util.ReadAllBytes(stream)); int lineNum = 0; @@ -1095,9 +1095,9 @@ namespace BizHawk.Client.Common } hf.Unbind(); } - else if (item.name.StartsWith("moviesram.")) + else if (item.Name.StartsWith("moviesram.")) { - hf.BindArchiveMember(item.index); + hf.BindArchiveMember(item.Index); var stream = hf.GetStream(); byte[] moviesram = Util.ReadAllBytes(stream); if (moviesram.Length != 0) @@ -1108,33 +1108,33 @@ namespace BizHawk.Client.Common } hf.Unbind(); } - else if (item.name == "port1") + else if (item.Name == "port1") { - hf.BindArchiveMember(item.index); + hf.BindArchiveMember(item.Index); var stream = hf.GetStream(); string port1 = Encoding.UTF8.GetString(Util.ReadAllBytes(stream)).Trim(); m.Header[PORT1] = port1; hf.Unbind(); } - else if (item.name == "port2") + else if (item.Name == "port2") { - hf.BindArchiveMember(item.index); + hf.BindArchiveMember(item.Index); var stream = hf.GetStream(); string port2 = Encoding.UTF8.GetString(Util.ReadAllBytes(stream)).Trim(); m.Header[PORT2] = port2; hf.Unbind(); } - else if (item.name == "projectid") + else if (item.Name == "projectid") { - hf.BindArchiveMember(item.index); + hf.BindArchiveMember(item.Index); var stream = hf.GetStream(); string projectid = Encoding.UTF8.GetString(Util.ReadAllBytes(stream)).Trim(); m.Header[PROJECTID] = projectid; hf.Unbind(); } - else if (item.name == "rerecords") + else if (item.Name == "rerecords") { - hf.BindArchiveMember(item.index); + hf.BindArchiveMember(item.Index); var stream = hf.GetStream(); string rerecords = Encoding.UTF8.GetString(Util.ReadAllBytes(stream)); int rerecordCount; @@ -1150,24 +1150,24 @@ namespace BizHawk.Client.Common m.Header.Rerecords = (ulong)rerecordCount; hf.Unbind(); } - else if (item.name.EndsWith(".sha256")) + else if (item.Name.EndsWith(".sha256")) { - hf.BindArchiveMember(item.index); + hf.BindArchiveMember(item.Index); var stream = hf.GetStream(); string rom = Encoding.UTF8.GetString(Util.ReadAllBytes(stream)).Trim(); - int pos = item.name.LastIndexOf(".sha256"); - string name = item.name.Substring(0, pos); + int pos = item.Name.LastIndexOf(".sha256"); + string name = item.Name.Substring(0, pos); m.Header[SHA256 + "_" + name] = rom; hf.Unbind(); } - else if (item.name == "savestate") + else if (item.Name == "savestate") { errorMsg = "Movies that begin with a savestate are not supported."; return null; } - else if (item.name == "subtitles") + else if (item.Name == "subtitles") { - hf.BindArchiveMember(item.index); + hf.BindArchiveMember(item.Index); var stream = hf.GetStream(); string subtitles = Encoding.UTF8.GetString(Util.ReadAllBytes(stream)); using (StringReader reader = new StringReader(subtitles)) @@ -1178,25 +1178,25 @@ namespace BizHawk.Client.Common } hf.Unbind(); } - else if (item.name == "starttime.second") + else if (item.Name == "starttime.second") { - hf.BindArchiveMember(item.index); + hf.BindArchiveMember(item.Index); var stream = hf.GetStream(); string startSecond = Encoding.UTF8.GetString(Util.ReadAllBytes(stream)).Trim(); m.Header[STARTSECOND] = startSecond; hf.Unbind(); } - else if (item.name == "starttime.subsecond") + else if (item.Name == "starttime.subsecond") { - hf.BindArchiveMember(item.index); + hf.BindArchiveMember(item.Index); var stream = hf.GetStream(); string startSubSecond = Encoding.UTF8.GetString(Util.ReadAllBytes(stream)).Trim(); m.Header[STARTSUBSECOND] = startSubSecond; hf.Unbind(); } - else if (item.name == "systemid") + else if (item.Name == "systemid") { - hf.BindArchiveMember(item.index); + hf.BindArchiveMember(item.Index); var stream = hf.GetStream(); string systemid = Encoding.UTF8.GetString(Util.ReadAllBytes(stream)).Trim(); m.Header.Comments.Add(EMULATIONORIGIN + " " + systemid); diff --git a/BizHawk.Client.EmuHawk/ArchiveChooser.cs b/BizHawk.Client.EmuHawk/ArchiveChooser.cs index 0f54201748..7e2b248698 100644 --- a/BizHawk.Client.EmuHawk/ArchiveChooser.cs +++ b/BizHawk.Client.EmuHawk/ArchiveChooser.cs @@ -36,9 +36,9 @@ namespace BizHawk.Client.EmuHawk var item = items[i]; var lvi = new ListViewItem { Tag = i }; lvi.SubItems.Add(new ListViewItem.ListViewSubItem()); - lvi.Text = item.name; - long size = item.size; - var extension = Path.GetExtension(item.name); + lvi.Text = item.Name; + long size = item.Size; + var extension = Path.GetExtension(item.Name); if (extension != null && (size % 1024 == 16 && extension.ToUpper() == ".NES")) size -= 16; lvi.SubItems[1].Text = Util.FormatFileSize(size); diff --git a/BizHawk.Common/HawkFile.cs b/BizHawk.Common/HawkFile.cs index f9d631d5be..8ec408862d 100644 --- a/BizHawk.Common/HawkFile.cs +++ b/BizHawk.Common/HawkFile.cs @@ -3,15 +3,29 @@ using System.Collections.Generic; using System.IO; using System.Linq; -//the HawkFile class is excessively engineered with the IHawkFileArchiveHandler to decouple the archive handling from the basic file handling. -//This is so we could drop in an unamanged dearchiver library optionally later as a performance optimization without ruining the portability of the code. -//Also, we want to be able to use HawkFiles in BizHawk.Common withuot bringing in a large 7-zip dependency - +// the HawkFile class is excessively engineered with the IHawkFileArchiveHandler to decouple the archive handling from the basic file handling. +// This is so we could drop in an unamanged dearchiver library optionally later as a performance optimization without ruining the portability of the code. +// Also, we want to be able to use HawkFiles in BizHawk.Common withuot bringing in a large 7-zip dependency namespace BizHawk.Common { - //todo: - //split into "bind" and "open (the bound thing)" - //scan archive to flatten interior directories down to a path (maintain our own archive item list) + // TODO: + // split into "bind" and "open (the bound thing)" + // scan archive to flatten interior directories down to a path (maintain our own archive item list) + + /// + /// Bridge between HawkFile and the frontend's implementation of archive management + /// + public interface IHawkFileArchiveHandler : IDisposable + { + // TODO - could this receive a hawkfile itself? possibly handy, in very clever scenarios of mounting fake files + bool CheckSignature(string fileName, out int offset, out bool isExecutable); + + List Scan(); + + IHawkFileArchiveHandler Construct(string path); + + void ExtractFile(int index, Stream stream); + } /// /// HawkFile allows a variety of objects (actual files, archive members) to be treated as normal filesystem objects to be opened, closed, and read. @@ -21,10 +35,92 @@ namespace BizHawk.Common /// public sealed class HawkFile : IDisposable { + private bool _exists; + private bool _rootExists; + private string _rootPath; + private string _memberPath; + private Stream _rootStream, _boundStream; + private IHawkFileArchiveHandler _extractor; + private List _archiveItems; + private int? _boundIndex; + + public HawkFile() { } + /// /// Set this with an instance which can construct archive handlers as necessary for archive handling. /// - public static IHawkFileArchiveHandler ArchiveHandlerFactory; + public static IHawkFileArchiveHandler ArchiveHandlerFactory { get; set; } + + /// + /// Gets a value indicating whether a bound file exists. if there is no bound file, it can't exist + /// + public bool Exists { get { return _exists; } } + + /// + /// Gets the directory containing the root + /// + public string Directory { get { return Path.GetDirectoryName(_rootPath); } } + + /// + /// Gets a value indicating whether this instance is bound + /// + public bool IsBound { get { return _boundStream != null; } } + + /// + /// returns the complete canonical full path ("c:\path\to\archive|member") of the bound file + /// + public string CanonicalFullPath { get { return MakeCanonicalName(_rootPath, _memberPath); } } + + /// + /// returns the complete canonical name ("archive|member") of the bound file + /// + public string CanonicalName { get { return MakeCanonicalName(Path.GetFileName(_rootPath), _memberPath); } } + + /// + /// returns the virtual name of the bound file (disregarding the archive) + /// + public string Name { get { return GetBoundNameFromCanonical(MakeCanonicalName(_rootPath, _memberPath)); } } + + /// + /// returns the extension of Name + /// + public string Extension { get { return Path.GetExtension(Name).ToUpper(); } } + + /// + /// Indicates whether this file is an archive + /// + public bool IsArchive { get { return _extractor != null; } } + + public IList ArchiveItems + { + get + { + if (!IsArchive) + { + throw new InvalidOperationException("Cant get archive items from non-archive"); + } + + return _archiveItems; + } + } + + /// + /// returns a stream for the currently bound file + /// + public Stream GetStream() + { + if (_boundStream == null) + { + throw new InvalidOperationException("HawkFile: Can't call GetStream() before youve successfully bound something!"); + } + + return _boundStream; + } + + public int? GetBoundIndex() + { + return _boundIndex; + } /// /// Utility: Uses full HawkFile processing to determine whether a file exists at the provided path @@ -44,154 +140,77 @@ namespace BizHawk.Common { using (var file = new HawkFile(path)) { - if (!file.Exists) throw new FileNotFoundException(path); + if (!file.Exists) + { + throw new FileNotFoundException(path); + } + using (Stream stream = file.GetStream()) { - MemoryStream ms = new MemoryStream((int)stream.Length); + var ms = new MemoryStream((int)stream.Length); stream.CopyTo(ms); return ms.GetBuffer(); } } } - - /// - /// returns whether a bound file exists. if there is no bound file, it can't exist - /// - public bool Exists { get { return exists; } } - - /// - /// gets the directory containing the root - /// - public string Directory { get { return Path.GetDirectoryName(rootPath); } } - - /// - /// returns a stream for the currently bound file - /// - public Stream GetStream() - { - if (boundStream == null) - throw new InvalidOperationException("HawkFile: Can't call GetStream() before youve successfully bound something!"); - return boundStream; - } - - /// - /// indicates whether this instance is bound - /// - public bool IsBound { get { return boundStream != null; } } - - /// - /// returns the complete canonical full path ("c:\path\to\archive|member") of the bound file - /// - public string CanonicalFullPath { get { return MakeCanonicalName(rootPath, memberPath); } } - - /// - /// returns the complete canonical name ("archive|member") of the bound file - /// - public string CanonicalName { get { return MakeCanonicalName(Path.GetFileName(rootPath), memberPath); } } - - /// - /// returns the virtual name of the bound file (disregarding the archive) - /// - public string Name { get { return GetBoundNameFromCanonical(MakeCanonicalName(rootPath, memberPath)); } } - - /// - /// returns the extension of Name - /// - public string Extension { get { return Path.GetExtension(Name).ToUpper(); } } - - /// - /// Indicates whether this file is an archive - /// - public bool IsArchive { get { return extractor != null; } } - - int? BoundIndex; - - public int? GetBoundIndex() - { - return BoundIndex; - } - - - //public class ArchiveItem - //{ - // public string name; - // public long size; - // public int index; - //} - - public IList ArchiveItems - { - get - { - if (!IsArchive) throw new InvalidOperationException("Cant get archive items from non-archive"); - return archiveItems; - } - } - /// /// these extensions won't even be tried as archives (removes spurious archive detects since some of the signatures are pretty damn weak) /// public string[] NonArchiveExtensions = new string[] { }; - //--- - bool exists; - bool rootExists; - string rootPath; - string memberPath; - Stream rootStream, boundStream; - IHawkFileArchiveHandler extractor; - List archiveItems; - - public HawkFile() - { - } - public void Open(string path) { - if (rootPath != null) throw new InvalidOperationException("Don't reopen a HawkFile."); + if (_rootPath != null) + { + throw new InvalidOperationException("Don't reopen a HawkFile."); + } string autobind = null; bool isArchivePath = IsCanonicalArchivePath(path); if (isArchivePath) { - string[] parts = path.Split('|'); + var parts = path.Split('|'); path = parts[0]; autobind = parts[1]; } var fi = new FileInfo(path); - rootExists = fi.Exists; + _rootExists = fi.Exists; if (fi.Exists == false) + { return; + } - rootPath = path; - exists = true; + _rootPath = path; + _exists = true; AnalyzeArchive(path); - if (extractor == null) + if (_extractor == null) { - rootStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); - //we could autobind here, but i dont want to - //bind it later with the desired extensions. + _rootStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); + // we could autobind here, but i dont want to + // bind it later with the desired extensions. } if (autobind == null) { - //non-archive files can be automatically bound this way + // non-archive files can be automatically bound this way if (!isArchivePath) + { BindRoot(); + } } else { autobind = autobind.ToUpperInvariant(); - if (extractor != null) + if (_extractor != null) { - var scanResults = extractor.Scan(); + var scanResults = _extractor.Scan(); for (int i = 0; i < scanResults.Count; i++) { - if (scanResults[i].name.ToUpperInvariant() == autobind) + if (scanResults[i].Name.ToUpperInvariant() == autobind) { BindArchiveMember(i); return; @@ -199,7 +218,7 @@ namespace BizHawk.Common } } - exists = false; + _exists = false; } } @@ -211,13 +230,12 @@ namespace BizHawk.Common Open(path); } - /// /// binds the specified ArchiveItem which you should have gotten by interrogating an archive hawkfile /// public HawkFile BindArchiveMember(HawkFileArchiveItem item) { - return BindArchiveMember(item.archiveIndex); + return BindArchiveMember(item.ArchiveIndex); } /// @@ -225,7 +243,7 @@ namespace BizHawk.Common /// public HawkFileArchiveItem FindArchiveMember(string name) { - return ArchiveItems.FirstOrDefault(ai => ai.name == name); + return ArchiveItems.FirstOrDefault(ai => ai.Name == name); } /// @@ -234,8 +252,12 @@ namespace BizHawk.Common public HawkFile BindArchiveMember(string name) { var ai = FindArchiveMember(name); - if (ai == null) return null; - else return BindArchiveMember(ai); + if (ai == null) + { + return null; + } + + return BindArchiveMember(ai); } /// @@ -243,16 +265,23 @@ namespace BizHawk.Common /// public HawkFile BindArchiveMember(int index) { - if (!rootExists) return this; - if (boundStream != null) throw new InvalidOperationException("stream already bound!"); + if (!_rootExists) + { + return this; + } - boundStream = new MemoryStream(); - int archiveIndex = archiveItems[index].archiveIndex; - extractor.ExtractFile(archiveIndex, boundStream); - boundStream.Position = 0; - memberPath = archiveItems[index].name; //TODO - maybe go through our own list of names? maybe not, its indexes dont match.. + if (_boundStream != null) + { + throw new InvalidOperationException("stream already bound!"); + } + + _boundStream = new MemoryStream(); + int archiveIndex = _archiveItems[index].ArchiveIndex; + _extractor.ExtractFile(archiveIndex, _boundStream); + _boundStream.Position = 0; + _memberPath = _archiveItems[index].Name; // TODO - maybe go through our own list of names? maybe not, its indexes dont match.. Console.WriteLine("HawkFile bound " + CanonicalFullPath); - BoundIndex = archiveIndex; + _boundIndex = archiveIndex; return this; } @@ -261,18 +290,22 @@ namespace BizHawk.Common /// public void Unbind() { - if (boundStream != null && boundStream != rootStream) boundStream.Close(); - boundStream = null; - memberPath = null; - BoundIndex = null; + if (_boundStream != null && _boundStream != _rootStream) + { + _boundStream.Close(); + } + + _boundStream = null; + _memberPath = null; + _boundIndex = null; } /// /// causes the root to be bound (in the case of non-archive files) /// - void BindRoot() + private void BindRoot() { - boundStream = rootStream; + _boundStream = _rootStream; Console.WriteLine("HawkFile bound " + CanonicalFullPath); } @@ -295,34 +328,42 @@ namespace BizHawk.Common /// /// Binds the first item in the archive (or the file itself) if the extension matches one of the supplied templates. - /// You probably should not use this. use BindSoleItemOf or the archive chooser instead + /// You probably should not use use BindSoleItemOf or the archive chooser instead /// public HawkFile BindFirstOf(params string[] extensions) { return BindByExtensionCore(true, extensions); } - HawkFile BindByExtensionCore(bool first, params string[] extensions) + private HawkFile BindByExtensionCore(bool first, params string[] extensions) { - if (!rootExists) return this; - if (boundStream != null) throw new InvalidOperationException("stream already bound!"); - - if (extractor == null) + if (!_rootExists) { - //open uncompressed file - string extension = Path.GetExtension(rootPath).Substring(1).ToUpperInvariant(); + return this; + } + + if (_boundStream != null) + { + throw new InvalidOperationException("stream already bound!"); + } + + if (_extractor == null) + { + // open uncompressed file + var extension = Path.GetExtension(_rootPath).Substring(1).ToUpperInvariant(); if (extensions.Length == 0 || extension.In(extensions)) { BindRoot(); } + return this; } var candidates = new List(); - for (int i = 0; i < archiveItems.Count; i++) + for (int i = 0; i < _archiveItems.Count; i++) { - var e = archiveItems[i]; - var extension = Path.GetExtension(e.name).ToUpperInvariant(); + var e = _archiveItems[i]; + var extension = Path.GetExtension(e.Name).ToUpperInvariant(); extension = extension.TrimStart('.'); if (extensions.Length == 0 || extension.In(extensions)) { @@ -331,24 +372,31 @@ namespace BizHawk.Common BindArchiveMember(i); return this; } + candidates.Add(i); } } + if (candidates.Count == 1) + { BindArchiveMember(candidates[0]); + } + return this; } - void ScanArchive() + private void ScanArchive() { - archiveItems = extractor.Scan(); + _archiveItems = _extractor.Scan(); } private void AnalyzeArchive(string path) { - //no archive handler == no analysis + // no archive handler == no analysis if (ArchiveHandlerFactory == null) + { return; + } int offset; bool isExecutable; @@ -359,16 +407,16 @@ namespace BizHawk.Common if (ArchiveHandlerFactory.CheckSignature(path, out offset, out isExecutable)) { - extractor = ArchiveHandlerFactory.Construct(path); + _extractor = ArchiveHandlerFactory.Construct(path); try { ScanArchive(); } catch { - extractor.Dispose(); - extractor = null; - archiveItems = null; + _extractor.Dispose(); + _extractor = null; + _archiveItems = null; } } } @@ -377,11 +425,18 @@ namespace BizHawk.Common { Unbind(); - if (extractor != null) extractor.Dispose(); - if (rootStream != null) rootStream.Dispose(); + if (_extractor != null) + { + _extractor.Dispose(); + } - extractor = null; - rootStream = null; + if (_rootStream != null) + { + _rootStream.Dispose(); + } + + _extractor = null; + _rootStream = null; } /// @@ -389,7 +444,7 @@ namespace BizHawk.Common /// static bool IsCanonicalArchivePath(string path) { - return (path.IndexOf('|') != -1); + return path.IndexOf('|') != -1; } /// @@ -405,7 +460,7 @@ namespace BizHawk.Common /// static string GetBoundNameFromCanonical(string canonical) { - string[] parts = canonical.Split('|'); + var parts = canonical.Split('|'); return parts[parts.Length - 1]; } @@ -414,27 +469,14 @@ namespace BizHawk.Common /// string MakeCanonicalName(string root, string member) { - if (member == null) return root; - else return string.Format("{0}|{1}", root, member); + if (member == null) + { + return root; + } + + return string.Format("{0}|{1}", root, member); } - - } //class HawkFile - - - /// - /// Bridge between HawkFile and the frontend's implementation of archive management - /// - public interface IHawkFileArchiveHandler : IDisposable - { - //todo - could this receive a hawkfile itself? possibly handy, in very clever scenarios of mounting fake files - bool CheckSignature(string fileName, out int offset, out bool isExecutable); - - List Scan(); - - IHawkFileArchiveHandler Construct(string path); - - void ExtractFile(int index, Stream stream); - } + } /// /// Members returned by IHawkFileArchiveHandler @@ -442,25 +484,24 @@ namespace BizHawk.Common public class HawkFileArchiveItem { /// - /// member name + /// Gets or sets the member name /// - public string name; + public string Name { get; set; } /// - /// size of member file + /// Gets or sets the size of member file /// - public long size; + public long Size { get; set; } /// - /// the index of this archive item + /// Gets or sets the index of this archive item /// - public int index; + public int Index { get; set; } /// - /// the index WITHIN THE ARCHIVE (for internal tracking by a IHawkFileArchiveHandler) of the member + /// Gets or sets the index WITHIN THE ARCHIVE (for internal tracking by a IHawkFileArchiveHandler) of the member /// - public int archiveIndex; + public int ArchiveIndex { get; set; } } - -} //namespace BizHawk.Common +} \ No newline at end of file diff --git a/BizHawk.Common/MruStack.cs b/BizHawk.Common/MruStack.cs index 72f915dea0..9128174c13 100644 --- a/BizHawk.Common/MruStack.cs +++ b/BizHawk.Common/MruStack.cs @@ -2,52 +2,61 @@ { public class MruStack { - private readonly T[] store; - private int count; - private int head; - - public int Count { get { return count; } } + private readonly T[] _store; + private int _count; + private int _head; public MruStack(int capacity) { - store = new T[capacity]; + _store = new T[capacity]; Clear(); } + public int Count { get { return _count; } } + public void Clear() { - head = 0; - count = 0; - for (int i = 0; i < store.Length; i++) - store[i] = default(T); + _head = 0; + _count = 0; + for (int i = 0; i < _store.Length; i++) + { + _store[i] = default(T); + } } public void Push(T value) { - store[head] = value; - head = (head + 1) % store.Length; + _store[_head] = value; + _head = (_head + 1) % _store.Length; - if (count < store.Length) - count++; + if (_count < _store.Length) + { + _count++; + } } public T Pop() { - if (count == 0) + if (_count == 0) + { return default(T); + } - head--; - if (head < 0) - head = store.Length - 1; - count--; - T value = store[head]; - store[head] = default(T); + _head--; + if (_head < 0) + { + _head = _store.Length - 1; + } + + _count--; + T value = _store[_head]; + _store[_head] = default(T); return value; } public bool HasElements() { - return count > 0; + return _count > 0; } } } \ No newline at end of file diff --git a/BizHawk.Common/SwitcherStream.cs b/BizHawk.Common/SwitcherStream.cs index 78d3688b5a..07d9809867 100644 --- a/BizHawk.Common/SwitcherStream.cs +++ b/BizHawk.Common/SwitcherStream.cs @@ -1,4 +1,3 @@ -using System; using System.IO; namespace BizHawk.Common @@ -12,56 +11,60 @@ namespace BizHawk.Common /// public class SwitcherStream : Stream { - //switchstream method? flush old stream? - Stream CurrStream = null; - - public void SetCurrStream(Stream str) { CurrStream = str; } + // switchstream method? flush old stream? + private Stream _currStream; public SwitcherStream() { } - public override bool CanRead { get { return CurrStream.CanRead; } } - public override bool CanSeek { get { return CurrStream.CanSeek; } } - public override bool CanWrite { get { return CurrStream.CanWrite; } } - public override void Flush() - { - CurrStream.Flush(); - } + public override bool CanRead { get { return _currStream.CanRead; } } + public override bool CanSeek { get { return _currStream.CanSeek; } } + public override bool CanWrite { get { return _currStream.CanWrite; } } - public override long Length { get { return CurrStream.Length; } } + public override long Length { get { return _currStream.Length; } } public override long Position { get { - return CurrStream.Position; + return _currStream.Position; } + set { - CurrStream.Position = Position; + _currStream.Position = Position; } } + public void SetCurrStream(Stream str) + { + _currStream = str; + } + + public override void Flush() + { + _currStream.Flush(); + } + public override int Read(byte[] buffer, int offset, int count) { - return CurrStream.Read(buffer, offset, count); + return _currStream.Read(buffer, offset, count); } public override long Seek(long offset, SeekOrigin origin) { - return CurrStream.Seek(offset, origin); + return _currStream.Seek(offset, origin); } public override void SetLength(long value) { - CurrStream.SetLength(value); + _currStream.SetLength(value); } public override void Write(byte[] buffer, int offset, int count) { - CurrStream.Write(buffer, offset, count); + _currStream.Write(buffer, offset, count); } } - } \ No newline at end of file diff --git a/BizHawk.Common/UndoHistory.cs b/BizHawk.Common/UndoHistory.cs index b96552c03f..05be8e689b 100644 --- a/BizHawk.Common/UndoHistory.cs +++ b/BizHawk.Common/UndoHistory.cs @@ -6,9 +6,7 @@ namespace BizHawk.Common public class UndoHistory { private List> _history = new List>(); - private int curPos; //1-based - - public bool Enabled { get; private set; } + private int _curPos; // 1-based public UndoHistory(bool enabled) { @@ -21,20 +19,16 @@ namespace BizHawk.Common Enabled = enabled; } - public void Clear() - { - _history = new List>(); - curPos = 0; - } + public bool Enabled { get; private set; } public bool CanUndo { - get { return Enabled && curPos > 1; } + get { return Enabled && _curPos > 1; } } public bool CanRedo { - get { return Enabled && curPos < _history.Count; } + get { return Enabled && _curPos < _history.Count; } } public bool HasHistory @@ -42,20 +36,26 @@ namespace BizHawk.Common get { return Enabled && _history.Any(); } } + public void Clear() + { + _history = new List>(); + _curPos = 0; + } + public void AddState(IEnumerable newState) { if (Enabled) { - if (curPos < _history.Count) + if (_curPos < _history.Count) { - for (int i = curPos + 1; i <= _history.Count; i++) + for (var i = _curPos + 1; i <= _history.Count; i++) { _history.Remove(_history[i - 1]); } } _history.Add(newState.ToList()); - curPos = _history.Count; + _curPos = _history.Count; } } @@ -63,26 +63,22 @@ namespace BizHawk.Common { if (CanUndo && Enabled) { - curPos--; - return _history[curPos - 1]; - } - else - { - return null; + _curPos--; + return _history[_curPos - 1]; } + + return Enumerable.Empty(); } public IEnumerable Redo() { if (CanRedo && Enabled) { - curPos++; - return _history[curPos - 1]; - } - else - { - return null; + _curPos++; + return _history[_curPos - 1]; } + + return Enumerable.Empty(); } } } diff --git a/BizHawk.Common/Util.cs b/BizHawk.Common/Util.cs index 2bc7c71375..e7981c80db 100644 --- a/BizHawk.Common/Util.cs +++ b/BizHawk.Common/Util.cs @@ -1,7 +1,7 @@ using System; +using System.Collections.Generic; using System.IO; using System.Text; -using System.Collections.Generic; namespace BizHawk.Common { @@ -10,14 +10,14 @@ namespace BizHawk.Common private static readonly char[] HexConvArr = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; private static System.Runtime.InteropServices.GCHandle HexConvHandle; - public static char* HexConvPtr { get; set; } - static Util() { HexConvHandle = System.Runtime.InteropServices.GCHandle.Alloc(HexConvArr, System.Runtime.InteropServices.GCHandleType.Pinned); HexConvPtr = (char*)HexConvHandle.AddrOfPinnedObject().ToPointer(); } + public static char* HexConvPtr { get; set; } + public static string Hash_MD5(byte[] data, int offset, int len) { using (var md5 = System.Security.Cryptography.MD5.Create()) @@ -58,11 +58,11 @@ namespace BizHawk.Common public static int SaveRamBytesUsed(byte[] saveRam) { - for (int j = saveRam.Length - 1; j >= 0; j--) + for (var i = saveRam.Length - 1; i >= 0; i--) { - if (saveRam[j] != 0) + if (saveRam[i] != 0) { - return j + 1; + return i + 1; } } @@ -73,7 +73,7 @@ namespace BizHawk.Common public static string ReadStringFixedAscii(this BinaryReader r, int bytes) { var read = new byte[bytes]; - for (int b = 0; b < bytes; b++) + for (var b = 0; b < bytes; b++) { read[b] = r.ReadByte(); } @@ -84,7 +84,7 @@ namespace BizHawk.Common public static string ReadStringAsciiZ(this BinaryReader r) { var sb = new StringBuilder(); - for (; ; ) + for (;;) { int b = r.ReadByte(); if (b <= 0) @@ -128,7 +128,7 @@ namespace BizHawk.Common int d = 0; for (int j = 0; j < 2; j++) { - var c = char.ToLower(str[i * 2 + j]); + var c = char.ToLower(str[(i * 2) + j]); if (c >= '0' && c <= '9') { d += c - '0'; @@ -146,11 +146,11 @@ namespace BizHawk.Common { d <<= 4; } - } ms.WriteByte((byte)d); } + return ms.ToArray(); } @@ -346,11 +346,11 @@ namespace BizHawk.Common public static string FormatFileSize(long filesize) { - Decimal size = filesize; + decimal size = filesize; - Decimal OneKiloByte = 1024M; - Decimal OneMegaByte = OneKiloByte * 1024M; - Decimal OneGigaByte = OneMegaByte * 1024M; + const decimal OneKiloByte = 1024M; + const decimal OneMegaByte = OneKiloByte * 1024M; + decimal OneGigaByte = OneMegaByte * 1024M; string suffix; if (size > 1024 * 1024 * 1024) @@ -373,26 +373,45 @@ namespace BizHawk.Common suffix = " B"; } - var precision = "2"; - return String.Format("{0:N" + precision + "}{1}", size, suffix); + const string precision = "2"; + return string.Format("{0:N" + precision + "}{1}", size, suffix); } // http://stackoverflow.com/questions/3928822/comparing-2-dictionarystring-string-instances public static bool DictionaryEqual( IDictionary first, IDictionary second) { - if (first == second) return true; - if ((first == null) || (second == null)) return false; - if (first.Count != second.Count) return false; + if (first == second) + { + return true; + } + + if ((first == null) || (second == null)) + { + return false; + } + + if (first.Count != second.Count) + { + return false; + } var comparer = EqualityComparer.Default; - foreach (KeyValuePair kvp in first) + foreach (var kvp in first) { TValue secondValue; - if (!second.TryGetValue(kvp.Key, out secondValue)) return false; - if (!comparer.Equals(kvp.Value, secondValue)) return false; + if (!second.TryGetValue(kvp.Key, out secondValue)) + { + return false; + } + + if (!comparer.Equals(kvp.Value, secondValue)) + { + return false; + } } + return true; } @@ -407,9 +426,11 @@ namespace BizHawk.Common { TValue ret; if (!dict.TryGetValue(key, out ret)) + { return defaultvalue; - else - return ret; + } + + return ret; } } @@ -420,6 +441,14 @@ namespace BizHawk.Common internal class SuperGloballyUniqueID { + private static readonly string StaticPart; + private static int ctr; + + static SuperGloballyUniqueID() + { + StaticPart = "bizhawk-" + System.Diagnostics.Process.GetCurrentProcess().Id + "-" + Guid.NewGuid(); + } + public static string Next() { int myctr; @@ -430,13 +459,5 @@ namespace BizHawk.Common return StaticPart + "-" + myctr; } - - static SuperGloballyUniqueID() - { - StaticPart = "bizhawk-" + System.Diagnostics.Process.GetCurrentProcess().Id + "-" + Guid.NewGuid(); - } - - private static readonly string StaticPart; - private static int ctr; } }