Misc code cleanups in BizHawk.Common

This commit is contained in:
adelikat 2017-04-13 13:57:58 -05:00
parent 1e05e8a29d
commit 3965af851f
24 changed files with 293 additions and 258 deletions

2
.gitignore vendored
View File

@ -68,3 +68,5 @@ ExternalCoreProjects/Virtu/bin/*.*
/psx/octoshock/bizhawk/Win32
/psx/octoshock/bizhawk/x64
/psx/octoshock/bizhawk/*.opendb
**/StyleCop.Cache

View File

@ -49,10 +49,10 @@ namespace BizHawk.Common
public AWEMemoryStream()
{
//bootstrap the datastructures
// bootstrap the datastructures
Position = 0;
//allocate the window (address space that we'll allocate physical pages into)
// allocate the window (address space that we'll allocate physical pages into)
mWindow = VirtualAlloc(IntPtr.Zero, new IntPtr(kBlockSize), AllocationType.RESERVE | AllocationType.PHYSICAL, MemoryProtection.READWRITE);
}
@ -420,12 +420,12 @@ namespace BizHawk.Common
public bool Map(IntPtr targetWindow)
{
//note: unmapping previous mapping seems unnecessary
// note: unmapping previous mapping seems unnecessary
if (pageList == null)
return false;
//map the desired physical pages
// map the desired physical pages
fixed (byte* pPageList = &pageList[0])
{
bool bResult = MapUserPhysicalPages(targetWindow, NumPages, new IntPtr(pPageList));

View File

@ -14,7 +14,7 @@
return (uint)((Byte8[v & 0xff] << 24) |
(Byte8[(v >> 8) & 0xff] << 16) |
(Byte8[(v >> 16) & 0xff] << 8) |
(Byte8[(v >> 24) & 0xff]));
Byte8[(v >> 24) & 0xff]);
}
private static void MakeByte8()

View File

@ -20,11 +20,13 @@ namespace BizHawk.Common
/// return true if an array type is not 0-based
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
private static bool IsNonZeroBaedArray(Type t)
{
if (!t.IsArray)
{
throw new InvalidOperationException();
}
// is there a better way to do this? i couldn't find any documentation...
return t.ToString().Contains('*');
}
@ -32,8 +34,6 @@ namespace BizHawk.Common
/// <summary>
/// return all instance fields of a type
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public static IEnumerable<FieldInfo> GetAllFields(Type t)
{
while (t != null)
@ -42,8 +42,11 @@ namespace BizHawk.Common
foreach (var f in t.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly))
{
if (f.GetCustomAttributes(typeof(DeepEqualsIgnoreAttribute), true).Length == 0)
{
yield return f;
}
}
t = t.BaseType;
}
}
@ -51,31 +54,29 @@ namespace BizHawk.Common
/// <summary>
/// test if two arrays are equal in contents; arrays should have same type
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="o1"></param>
/// <param name="o2"></param>
/// <returns></returns>
private static bool ArrayEquals<T>(T[] o1, T[] o2)
{
if (o1.Length != o2.Length)
{
return false;
}
for (int i = 0; i < o1.Length; i++)
{
if (!DeepEquals(o1[i], o2[i]))
{
return false;
}
}
return true;
}
static MethodInfo ArrayEqualsGeneric = typeof(DeepEquality).GetMethod("ArrayEquals", BindingFlags.NonPublic | BindingFlags.Static);
/// <summary>
/// test if two objects are equal field by field (with deep inspection of each field)
/// </summary>
/// <param name="o1"></param>
/// <param name="o2"></param>
/// <returns></returns>
public static bool DeepEquals(object o1, object o2)
{
if (o1 == o2)
@ -83,6 +84,7 @@ namespace BizHawk.Common
// reference equal, so nothing else to be done
return true;
}
Type t1 = o1.GetType();
Type t2 = o2.GetType();
if (t1 != t2)
@ -93,27 +95,30 @@ namespace BizHawk.Common
{
// it's not too hard to support thesse if needed
if (t1.GetArrayRank() > 1 || IsNonZeroBaedArray(t1))
{
throw new InvalidOperationException("Complex arrays not supported");
}
// this is actually pretty fast; it allows using fast ldelem and stelem opcodes on
// arbitrary array types without emitting custom IL
var method = ArrayEqualsGeneric.MakeGenericMethod(new Type[] { t1.GetElementType() });
return (bool)method.Invoke(null, new object[] { o1, o2 });
}
else if (t1.IsPrimitive)
if (t1.IsPrimitive)
{
return o1.Equals(o2);
}
else
foreach (var field in GetAllFields(t1))
{
foreach (var field in GetAllFields(t1))
if (!DeepEquals(field.GetValue(o1), field.GetValue(o2)))
{
if (!DeepEquals(field.GetValue(o1), field.GetValue(o2)))
return false;
return false;
}
return true;
}
}
return true;
}
}
}

View File

@ -20,7 +20,7 @@ namespace BizHawk.Common.BufferExtensions
private static readonly char[] HexConvArr = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
public unsafe static void SaveAsHexFast(this byte[] buffer, TextWriter writer)
public static unsafe void SaveAsHexFast(this byte[] buffer, TextWriter writer)
{
fixed (char* table = HexConvArr)
{
@ -35,6 +35,7 @@ namespace BizHawk.Common.BufferExtensions
}
}
}
writer.WriteLine();
}
@ -44,6 +45,7 @@ namespace BizHawk.Common.BufferExtensions
{
writer.Write("{0:X2}", buffer[i]);
}
writer.WriteLine();
}
@ -53,6 +55,7 @@ namespace BizHawk.Common.BufferExtensions
{
writer.Write("{0:X4}", b);
}
writer.WriteLine();
}
@ -62,6 +65,7 @@ namespace BizHawk.Common.BufferExtensions
{
writer.Write("{0:X4}", b);
}
writer.WriteLine();
}
@ -71,6 +75,7 @@ namespace BizHawk.Common.BufferExtensions
{
writer.Write("{0:X8}", b);
}
writer.WriteLine();
}
@ -80,6 +85,7 @@ namespace BizHawk.Common.BufferExtensions
{
writer.Write("{0:X8}", b);
}
writer.WriteLine();
}
@ -92,7 +98,7 @@ namespace BizHawk.Common.BufferExtensions
for (int i = 0; i < buffer.Length && i * 2 < hex.Length; i++)
{
var bytehex = "" + hex[i * 2] + hex[i * 2 + 1];
var bytehex = string.Empty + hex[i * 2] + hex[(i * 2) + 1];
buffer[i] = byte.Parse(bytehex, NumberStyles.HexNumber);
}
}
@ -128,7 +134,7 @@ namespace BizHawk.Common.BufferExtensions
for (int i = 0; i < buffer.Length && i * 4 < hex.Length; i++)
{
var shorthex = "" + hex[i * 4] + hex[(i * 4) + 1] + hex[(i * 4) + 2] + hex[(i * 4) + 3];
var shorthex = string.Empty + hex[i * 4] + hex[(i * 4) + 1] + hex[(i * 4) + 2] + hex[(i * 4) + 3];
buffer[i] = short.Parse(shorthex, NumberStyles.HexNumber);
}
}
@ -142,7 +148,7 @@ namespace BizHawk.Common.BufferExtensions
for (int i = 0; i < buffer.Length && i * 4 < hex.Length; i++)
{
var ushorthex = "" + hex[i * 4] + hex[(i * 4) + 1] + hex[(i * 4) + 2] + hex[(i * 4) + 3];
var ushorthex = string.Empty + hex[i * 4] + hex[(i * 4) + 1] + hex[(i * 4) + 2] + hex[(i * 4) + 3];
buffer[i] = ushort.Parse(ushorthex, NumberStyles.HexNumber);
}
}
@ -156,7 +162,6 @@ namespace BizHawk.Common.BufferExtensions
for (int i = 0; i < buffer.Length && i * 8 < hex.Length; i++)
{
//string inthex = "" + hex[i * 8] + hex[(i * 8) + 1] + hex[(i * 4) + 2] + hex[(i * 4) + 3] + hex[(i*4
var inthex = hex.Substring(i * 8, 8);
buffer[i] = int.Parse(inthex, NumberStyles.HexNumber);
}
@ -182,10 +187,10 @@ namespace BizHawk.Common.BufferExtensions
int result = Array.FindIndex(array, 0, array.Length, (byte b) =>
{
fidx = (b == pattern[fidx]) ? fidx + 1 : 0;
return (fidx == pattern.Length);
return fidx == pattern.Length;
});
return (result >= pattern.Length - 1);
return result >= pattern.Length - 1;
}
public static string HashMD5(this byte[] data, int offset, int len)
@ -216,8 +221,6 @@ namespace BizHawk.Common.BufferExtensions
return HashSHA1(data, 0, data.Length);
}
#region Helpers
private static int Hex2Int(char c)
{
if (c <= '9')
@ -232,7 +235,5 @@ namespace BizHawk.Common.BufferExtensions
return c - 'W';
}
#endregion
}
}

View File

@ -33,7 +33,7 @@ namespace BizHawk.Common.CollectionExtensions
}
}
//did we find it exactly?
// did we find it exactly?
if (min == max && keySelector(list[min]).CompareTo(key) == 0)
{
return min;
@ -41,8 +41,7 @@ namespace BizHawk.Common.CollectionExtensions
mid = min;
//we didnt find it. return something corresponding to lower_bound semantics
// we didnt find it. return something corresponding to lower_bound semantics
if (mid == list.Count)
{
return max; // had to go all the way to max before giving up; lower bound is max
@ -87,6 +86,7 @@ namespace BizHawk.Common.CollectionExtensions
return midItem;
}
}
if (min == max &&
keySelector(list[min]).CompareTo(key) == 0)
{
@ -99,13 +99,13 @@ namespace BizHawk.Common.CollectionExtensions
public static byte[] ToByteArray(this IEnumerable<bool> list)
{
var bits = new BitArray(list.ToArray());
byte [] bytes = new byte[bits.Length / 8 + ( bits.Length % 8 == 0 ? 0 : 1 )];
byte[] bytes = new byte[(bits.Length / 8) + (bits.Length % 8 == 0 ? 0 : 1)];
bits.CopyTo(bytes, 0);
return bytes;
}
/// <summary>
/// Converts any byte array into a bit array represented as a list of bools
/// Converts any byte array into a bit array represented as a list of booleans
/// </summary>
public static IEnumerable<bool> ToBools(this byte[] bytes)
{
@ -115,7 +115,5 @@ namespace BizHawk.Common.CollectionExtensions
return bools;
}
}
}

View File

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
@ -25,7 +24,7 @@ namespace BizHawk.Common.IOExtensions
}
// Read bytes from a BinaryReader and translate them into the UTF-8 string they represent.
//WHAT? WHY IS THIS NAMED ASCII BUT USING UTF8
// WHAT? WHY IS THIS NAMED ASCII BUT USING UTF8
public static string ReadStringFixedAscii(this BinaryReader r, int bytes)
{
var read = new byte[bytes];
@ -35,26 +34,30 @@ namespace BizHawk.Common.IOExtensions
public static string ReadStringUtf8NullTerminated(this BinaryReader br)
{
MemoryStream ms = new MemoryStream();
for (; ; )
var ms = new MemoryStream();
for (;;)
{
var b = br.ReadByte();
if (b == 0)
return System.Text.Encoding.UTF8.GetString(ms.ToArray());
{
return Encoding.UTF8.GetString(ms.ToArray());
}
ms.WriteByte(b);
}
}
public static void CopyTo(this Stream src, Stream dest)
{
int size = (src.CanSeek) ? Math.Min((int)(src.Length - src.Position), 0x2000) : 0x2000;
int size = src.CanSeek ? Math.Min((int)(src.Length - src.Position), 0x2000) : 0x2000;
byte[] buffer = new byte[size];
int n;
do
{
n = src.Read(buffer, 0, buffer.Length);
dest.Write(buffer, 0, n);
} while (n != 0);
}
while (n != 0);
}
public static void CopyTo(this MemoryStream src, Stream dest)

View File

@ -71,7 +71,7 @@ namespace BizHawk.Common.NumberExtensions
/// </summary>
public static int NumHexDigits(this long i)
{
//now this is a bit of a trick. if it was less than 0, it mustve been >= 0x80000000 and so takes all 8 digits
// now this is a bit of a trick. if it was less than 0, it mustve been >= 0x80000000 and so takes all 8 digits
if (i < 0)
{
return 8;
@ -105,11 +105,11 @@ namespace BizHawk.Common.NumberExtensions
/// </summary>
public static int Mod(this int a, int b)
{
return a - (b * (int)System.Math.Floor((float)a / b));
return a - (b * (int)Math.Floor((float)a / b));
}
/// <summary>
/// Force the value to be stricly between min and max (both exclued)
/// Force the value to be strictly between min and max (both exclued)
/// </summary>
/// <typeparam name="T">Anything that implements <see cref="IComparable{T}"/></typeparam>
/// <param name="val">Value that will be clamped</param>
@ -118,18 +118,17 @@ namespace BizHawk.Common.NumberExtensions
/// <returns>The value if strictly between min and max; otherwise min (or max depending of what is passed)</returns>
public static T Clamp<T>(this T val, T min, T max) where T : IComparable<T>
{
if(val.CompareTo(min) < 0)
if (val.CompareTo(min) < 0)
{
return min;
}
else if(val.CompareTo(max) > 0)
if (val.CompareTo(max) > 0)
{
return max;
}
else
{
return val;
}
return val;
}
}
}

View File

@ -2,7 +2,6 @@
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
@ -20,7 +19,6 @@ namespace BizHawk.Common.ReflectionExtensions
.Where(p => p.GetCustomAttributes(attributeType, false).Length > 0);
}
/// <summary>
/// Gets the description attribute from an object
/// </summary>
@ -63,7 +61,6 @@ namespace BizHawk.Common.ReflectionExtensions
/// <summary>
/// Gets the description attribute from a type
/// </summary>
/// <returns></returns>
public static string Description(this Type type)
{
var descriptions = (DescriptionAttribute[])
@ -87,7 +84,11 @@ namespace BizHawk.Common.ReflectionExtensions
public static T GetEnumFromDescription<T>(this string description)
{
var type = typeof(T);
if (!type.IsEnum) throw new InvalidOperationException();
if (!type.IsEnum)
{
throw new InvalidOperationException();
}
foreach (var field in type.GetFields())
{
var attribute = Attribute.GetCustomAttribute(field,
@ -114,7 +115,7 @@ namespace BizHawk.Common.ReflectionExtensions
/// <summary>
/// Takes an object and determines if it has methodName as a public method
/// </summary>
/// <returns>Returns whether or not the obj both contains the method name and the method is public</returns>
/// <returns>Returns whether or not the object both contains the method name and the method is public</returns>
public static bool HasExposedMethod(this object obj, string methodName)
{
var method = obj.GetType().GetMethod(methodName);
@ -172,7 +173,6 @@ namespace BizHawk.Common.ReflectionExtensions
/// <summary>
/// Takes an enum Type and generates a list of strings from the description attributes
/// </summary>
/// <returns></returns>
public static IEnumerable<string> GetEnumDescriptions(this Type type)
{
var vals = Enum.GetValues(type);
@ -188,13 +188,17 @@ namespace BizHawk.Common.ReflectionExtensions
return (T)o.GetType().GetCustomAttributes(typeof(T), false)[0];
}
/// <summary>
/// where the fields begin relative to the address an object references points to
/// </summary>
public static IntPtr ManagedFieldStart { get { return _managedfieldstart; } }
/// <summary>
/// where the fields begin relative to the address an object references points to
/// </summary>
public static IntPtr ManagedFieldStart => _managedfieldstart;
[StructLayout(LayoutKind.Explicit)]
private class Junkus { [FieldOffset(0)]public IntPtr s; }
private class Junkus
{
[FieldOffset(0)]
public IntPtr s;
}
static IntPtr _managedfieldstart = GetManagedOffset(typeof(Junkus).GetField("s"));
@ -202,7 +206,6 @@ namespace BizHawk.Common.ReflectionExtensions
/// the address of a field relative to the address an object reference of that type points to. this function is very expensive to call.
/// </summary>
/// <param name="field"></param>
/// <returns></returns>
public static IntPtr GetManagedOffset(this FieldInfo field)
{
Type type = field.DeclaringType;
@ -234,13 +237,13 @@ namespace BizHawk.Common.ReflectionExtensions
public static bool ThrowsError(this MethodInfo info)
{
var il = info.GetMethodBody().GetILAsByteArray();
return (il[il.Length - 1] == 0x7A);
return il[il.Length - 1] == 0x7A;
}
public static bool IsEmpty(this MethodInfo info)
{
var il = info.GetMethodBody().GetILAsByteArray();
return (il.Length == 1 && il[0] == 0x2A);
return il.Length == 1 && il[0] == 0x2A;
}
}
}

View File

@ -283,7 +283,6 @@ namespace BizHawk.Common.StringExtensions
}
else if (IsUnsigned(chr))
{
output.Append(chr);
}
@ -318,7 +317,7 @@ namespace BizHawk.Common.StringExtensions
/// <summary>
/// Takes any string and removes any value that is not a fixed point value (0-9 or .)
/// Note: only the first occurance of a . will be kept
/// Note: only the first occurrence of a . will be kept
/// </summary>
public static string OnlyFixedPoint(this string raw)
{
@ -353,7 +352,7 @@ namespace BizHawk.Common.StringExtensions
/// <summary>
/// Takes any string and removes any value that is not a float point value (0-9, -, or .)
/// Note: - is only valid as the first character, and only the first occurance of a . will be kept
/// Note: - is only valid as the first character, and only the first occurrence of a . will be kept
/// </summary>
public static string OnlyFloat(this string raw)
{

View File

@ -58,59 +58,59 @@ namespace BizHawk.Common
/// Gets a value indicating whether a bound file exists. if there is no bound file, it can't exist.
/// NOTE: this isn't set until the file is Opened. Not too great...
/// </summary>
public bool Exists { get { return _exists; } }
public bool Exists => _exists;
/// <summary>
/// <summary>
/// Gets the directory containing the root
/// </summary>
public string Directory { get { return Path.GetDirectoryName(_rootPath); } }
public string Directory => Path.GetDirectoryName(_rootPath);
/// <summary>
/// <summary>
/// Gets a value indicating whether this instance is bound
/// </summary>
public bool IsBound { get { return _boundStream != null; } }
public bool IsBound => _boundStream != null;
/// <summary>
/// <summary>
/// returns the complete canonical full path ("c:\path\to\archive|member") of the bound file
/// </summary>
public string CanonicalFullPath { get { return MakeCanonicalName(_rootPath, _memberPath); } }
public string CanonicalFullPath => MakeCanonicalName(_rootPath, _memberPath);
/// <summary>
/// <summary>
/// returns the complete canonical name ("archive|member") of the bound file
/// </summary>
public string CanonicalName { get { return MakeCanonicalName(Path.GetFileName(_rootPath), _memberPath); } }
public string CanonicalName => MakeCanonicalName(Path.GetFileName(_rootPath), _memberPath);
/// <summary>
/// <summary>
/// returns the virtual name of the bound file (disregarding the archive)
/// </summary>
public string Name { get { return GetBoundNameFromCanonical(MakeCanonicalName(_rootPath, _memberPath)); } }
public string Name => GetBoundNameFromCanonical(MakeCanonicalName(_rootPath, _memberPath));
/// <summary>
/// <summary>
/// returns the complete full path of the bound file, excluding the archive member portion
/// </summary>
public string FullPathWithoutMember { get { return _rootPath; } }
public string FullPathWithoutMember => _rootPath;
/// <summary>
/// <summary>
/// returns the member path part of the bound file
/// </summary>
public string ArchiveMemberPath { get { return _memberPath; } }
public string ArchiveMemberPath => _memberPath;
/// <summary>
/// <summary>
/// returns the extension of Name
/// </summary>
public string Extension { get { return Path.GetExtension(Name).ToUpper(); } }
public string Extension => Path.GetExtension(Name).ToUpper();
/// <summary>
/// <summary>
/// Indicates whether this file is an archive
/// </summary>
public bool IsArchive { get { return _isArchive; } }
public bool IsArchive => _isArchive;
/// <summary>
/// <summary>
/// Indicates whether the file is an archive member (IsArchive && IsBound[to member])
/// </summary>
public bool IsArchiveMember { get { return IsArchive && IsBound; } }
public bool IsArchiveMember => IsArchive && IsBound;
public IList<HawkFileArchiveItem> ArchiveItems
public IList<HawkFileArchiveItem> ArchiveItems
{
get
{
@ -202,7 +202,8 @@ namespace BizHawk.Common
var parts = path.Split('|');
path = parts[0];
_memberPath = parts[1];
//we're gonna assume, on parsing, that this is
// we're gonna assume, on parsing, that this is
_isArchive = true;
}
_rootPath = path;
@ -479,15 +480,8 @@ namespace BizHawk.Common
{
Unbind();
if (_extractor != null)
{
_extractor.Dispose();
}
if (_rootStream != null)
{
_rootStream.Dispose();
}
_extractor?.Dispose();
_rootStream?.Dispose();
_extractor = null;
_rootStream = null;
@ -496,7 +490,7 @@ namespace BizHawk.Common
/// <summary>
/// is the supplied path a canonical name including an archive?
/// </summary>
static bool IsCanonicalArchivePath(string path)
private static bool IsCanonicalArchivePath(string path)
{
return path.IndexOf('|') != -1;
}
@ -528,7 +522,7 @@ namespace BizHawk.Common
return root;
}
return string.Format("{0}|{1}", root, member);
return $"{root}|{member}";
}
public static IEnumerable<string> Util_ResolveLinks(IEnumerable<string> paths)

View File

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Common
{
@ -19,7 +16,10 @@ namespace BizHawk.Common
{
var ret = dll.Resolve(entryPoint);
if (ret == IntPtr.Zero)
throw new NullReferenceException(string.Format("Couldn't resolve entry point \"{0}\"", entryPoint));
{
throw new NullReferenceException($"Couldn't resolve entry point \"{entryPoint}\"");
}
return ret;
}
}

View File

@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Common
namespace BizHawk.Common
{
public interface IMonitor
{

View File

@ -8,16 +8,16 @@ namespace BizHawk.Common
{
public InstanceDll(string dllPath)
{
//copy the dll to a temp directory
// copy the dll to a temp directory
var path = TempFileCleaner.GetTempFilename(string.Format("{0}", Path.GetFileNameWithoutExtension(dllPath)),".dll",false);
using (var stream = new FileStream(path, FileMode.Create, System.Security.AccessControl.FileSystemRights.FullControl, FileShare.ReadWrite | FileShare.Delete, 4 * 1024, FileOptions.None))
using (var sdll = File.OpenRead(dllPath))
sdll.CopyTo(stream);
//try to locate dlls in the current directory (for libretro cores)
//this isnt foolproof but its a little better than nothing
//setting PWD temporarily doesnt work. that'd be ideal since it supposedly gets searched early on,
//but i guess not with SetDllDirectory in effect
// try to locate dlls in the current directory (for libretro cores)
// this isnt foolproof but its a little better than nothing
// setting PWD temporarily doesnt work. that'd be ideal since it supposedly gets searched early on,
// but i guess not with SetDllDirectory in effect
var envpath = Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Process);
try
{
@ -46,10 +46,13 @@ namespace BizHawk.Common
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, LoadLibraryFlags dwFlags);
[DllImport("kernel32.dll")]
static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
[DllImport("kernel32.dll")]
static extern bool FreeLibrary(IntPtr hModule);
@ -72,6 +75,6 @@ namespace BizHawk.Common
}
}
IntPtr _hModule;
private IntPtr _hModule;
}
}

View File

@ -20,23 +20,25 @@ namespace BizHawk.Common
}
// ============== Logging Domain Configuration ==============
private static readonly List<string> EnabledLogDomains = new List<string>();
public static void EnableDomain(string domain)
{
if (EnabledLogDomains.Contains(domain) == false)
{
EnabledLogDomains.Add(domain);
}
}
public static void DisableDomain(string domain)
{
if (EnabledLogDomains.Contains(domain))
{
EnabledLogDomains.Remove(domain);
}
}
// ============== Logging Action Configuration ==============
public static Action<string> LogAction = DefaultLogger;
// NOTEs are only logged if the domain is enabled.
@ -45,16 +47,17 @@ namespace BizHawk.Common
public static void Note(string domain, string msg, params object[] vals)
{
if (EnabledLogDomains.Contains(domain))
{
LogAction(String.Format(msg, vals));
}
}
public static void Error(string domain, string msg, params object[] vals)
{
LogAction(String.Format(msg, vals));
LogAction(string.Format(msg, vals));
}
// ============== Default Logger Action ==============
public static Stream HACK_LOG_STREAM;
private static readonly bool LogToConsole = false;
@ -66,10 +69,14 @@ namespace BizHawk.Common
private static void DefaultLogger(string message)
{
if (LogToConsole)
{
Console.WriteLine(message);
}
if (LogToFile && writer == null)
{
writer = new StreamWriter(LogFilename);
}
if (LogToFile)
{

View File

@ -12,9 +12,9 @@
Clear();
}
public int Count { get { return _count; } }
public int Count => _count;
public void Clear()
public void Clear()
{
_head = 0;
_count = 0;

View File

@ -167,6 +167,7 @@ namespace BizHawk.Common
curr = curr.Next;
}
System.Diagnostics.Debug.Assert(curr == null);
}

View File

@ -1,32 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace BizHawk.Common
{
public class SimpleTime : IDisposable
{
private Stopwatch w;
private Action<int> f;
private readonly Stopwatch _w;
private readonly Action<int> _f;
public SimpleTime(string s)
:this(t => Console.WriteLine("Elapsed time for {0}: {1}ms", s, t))
: this(t => Console.WriteLine("Elapsed time for {0}: {1}ms", s, t))
{
}
public SimpleTime(Action<int> f)
{
this.f = f;
w = new Stopwatch();
w.Start();
_f = f;
_w = new Stopwatch();
_w.Start();
}
public void Dispose()
{
w.Stop();
f((int)w.ElapsedMilliseconds);
_w.Stop();
_f((int)_w.ElapsedMilliseconds);
}
}
}

View File

@ -24,13 +24,15 @@ namespace BizHawk.Common
/// </summary>
public bool DenySeekHack = false;
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 bool CanRead => _currStream.CanRead;
public override long Length { get { return _currStream.Length; } }
public override bool CanSeek => _currStream.CanSeek;
public override long Position
public override bool CanWrite => _currStream.CanWrite;
public override long Length => _currStream.Length;
public override long Position
{
get
{
@ -41,9 +43,14 @@ namespace BizHawk.Common
{
if (DenySeekHack)
{
if (value == 0) return;
else throw new InvalidOperationException("Cannot set position to non-zero in a SwitcherStream with DenySeekHack=true");
if (value == 0)
{
return;
}
throw new InvalidOperationException("Cannot set position to non-zero in a SwitcherStream with DenySeekHack=true");
}
_currStream.Position = value;
}
}
@ -67,9 +74,14 @@ namespace BizHawk.Common
{
if (DenySeekHack)
{
if (offset == 0 && origin == SeekOrigin.Begin) return 0;
else throw new InvalidOperationException("Cannot call Seek with non-zero offset or non-Begin origin in a SwitcherStream with DenySeekHack=true");
if (offset == 0 && origin == SeekOrigin.Begin)
{
return 0;
}
throw new InvalidOperationException("Cannot call Seek with non-zero offset or non-Begin origin in a SwitcherStream with DenySeekHack=true");
}
return _currStream.Seek(offset, origin);
}

View File

@ -1,88 +1,101 @@
using System;
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace BizHawk.Common
{
/// <summary>
/// Starts a thread which cleans any filenames in %temp% beginning with bizhawk.bizdelete.
/// Files shouldn't be named that unless they're safe to delete, but notably, they may stil be in use. That won't hurt this component.
/// When they're no longer in use, this component will then be able to delete them.
/// </summary>
public static class TempFileCleaner
{
//todo - manage paths other than %temp%, make not static, or allow adding multiple paths to static instance
public static string GetTempFilename(string friendlyname, string extension = null, bool delete = true)
{
string guidPart = Guid.NewGuid().ToString();
var fname = string.Format("biz-{0}-{1}-{2}{3}", System.Diagnostics.Process.GetCurrentProcess().Id, friendlyname, guidPart, extension ?? "");
if (delete) fname = RenameTempFilenameForDelete(fname);
return Path.Combine(Path.GetTempPath(), fname);
}
public static string RenameTempFilenameForDelete(string path)
{
string filename = Path.GetFileName(path);
string dir = Path.GetDirectoryName(path);
if (!filename.StartsWith("biz-")) throw new InvalidOperationException();
filename = "bizdelete-" + filename.Remove(0, 4);
return Path.Combine(dir, filename);
}
public static void Start()
{
lock (typeof(TempFileCleaner))
{
if (thread != null)
return;
thread = new System.Threading.Thread(ThreadProc);
thread.IsBackground = true;
thread.Priority = System.Threading.ThreadPriority.Lowest;
thread.Start();
}
using System.Runtime.InteropServices;
using System.Threading;
namespace BizHawk.Common
{
/// <summary>
/// Starts a thread which cleans any filenames in %temp% beginning with bizhawk.bizdelete.
/// Files shouldn't be named that unless they're safe to delete, but notably, they may stil be in use. That won't hurt this component.
/// When they're no longer in use, this component will then be able to delete them.
/// </summary>
public static class TempFileCleaner
{
// TODO - manage paths other than %temp%, make not static, or allow adding multiple paths to static instance
public static string GetTempFilename(string friendlyname, string extension = null, bool delete = true)
{
string guidPart = Guid.NewGuid().ToString();
var fname = $"biz-{System.Diagnostics.Process.GetCurrentProcess().Id}-{friendlyname}-{guidPart}{extension ?? string.Empty}";
if (delete)
{
fname = RenameTempFilenameForDelete(fname);
}
return Path.Combine(Path.GetTempPath(), fname);
}
public static string RenameTempFilenameForDelete(string path)
{
string filename = Path.GetFileName(path);
string dir = Path.GetDirectoryName(path);
if (!filename.StartsWith("biz-"))
{
throw new InvalidOperationException();
}
filename = "bizdelete-" + filename.Remove(0, 4);
return Path.Combine(dir, filename);
}
public static void Start()
{
lock (typeof(TempFileCleaner))
{
if (thread != null)
{
return;
}
thread = new Thread(ThreadProc)
{
IsBackground = true,
Priority = ThreadPriority.Lowest
};
thread.Start();
}
}
#if WINDOWS
[DllImport("kernel32.dll", EntryPoint = "DeleteFileW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)]
static extern bool DeleteFileW([MarshalAs(UnmanagedType.LPWStr)]string lpFileName);
#endif
static void ThreadProc()
{
var di = new DirectoryInfo(Path.GetTempPath());
for (;;)
{
var fis = di.GetFiles("bizdelete-*");
foreach (var fi in fis)
{
try
{
//SHUT. UP. THE. EXCEPTIONS.
static extern bool DeleteFileW([MarshalAs(UnmanagedType.LPWStr)]string lpFileName);
#endif
static void ThreadProc()
{
var di = new DirectoryInfo(Path.GetTempPath());
for (;;)
{
var fis = di.GetFiles("bizdelete-*");
foreach (var fi in fis)
{
try
{
// SHUT. UP. THE. EXCEPTIONS.
#if WINDOWS
DeleteFileW(fi.FullName);
#else
fi.Delete();
#endif
}
catch
{
}
//try not to do more than one thing per frame
System.Threading.Thread.Sleep(100);
}
//try not to slam the filesystem too hard, we dont want this to cause any hiccups
System.Threading.Thread.Sleep(5000);
}
}
public static void Stop()
{
}
static System.Threading.Thread thread;
}
DeleteFileW(fi.FullName);
#else
fi.Delete();
#endif
}
catch
{
}
// try not to do more than one thing per frame
Thread.Sleep(100);
}
// try not to slam the filesystem too hard, we dont want this to cause any hiccups
Thread.Sleep(5000);
}
}
public static void Stop()
{
}
static Thread thread;
}
}

View File

@ -8,7 +8,7 @@ namespace BizHawk.Common
private List<List<T>> _history = new List<List<T>>();
private int _curPos; // 1-based
public int MaxUndoLevels { get; set; }
public int MaxUndoLevels { get; }
public UndoHistory(bool enabled)
{
@ -22,24 +22,15 @@ namespace BizHawk.Common
Enabled = enabled;
}
public bool Enabled { get; private set; }
public bool Enabled { get; }
public bool CanUndo
{
get { return Enabled && _curPos > 1; }
}
public bool CanUndo => Enabled && _curPos > 1;
public bool CanRedo
{
get { return Enabled && _curPos < _history.Count; }
}
public bool CanRedo => Enabled && _curPos < _history.Count;
public bool HasHistory
{
get { return Enabled && _history.Any(); }
}
public bool HasHistory => Enabled && _history.Any();
public void Clear()
public void Clear()
{
_history = new List<List<T>>();
_curPos = 0;

View File

@ -18,7 +18,10 @@ namespace BizHawk.Common
public void Dispose()
{
foreach (var h in HGlobals)
{
Marshal.FreeHGlobal(h);
}
HGlobals.Clear();
}
}

View File

@ -1,10 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using BizHawk.Common.BufferExtensions;
using System.Reflection;
using System.Text;
namespace BizHawk.Common
{
@ -29,10 +27,13 @@ namespace BizHawk.Common
/// </summary>
public static bool TryWaitForFileToVanish(string path)
{
for (int i = 0; i < 25; i++) //250ms
for (int i = 0; i < 25; i++) // 250ms
{
if (!File.Exists(path))
{
return true;
}
System.Threading.Thread.Sleep(10);
}
return false;
@ -44,32 +45,36 @@ namespace BizHawk.Common
/// </summary>
public static bool TryMoveBackupFile(string pathWant, string pathBackup)
{
//If the path we want is available we dont actually have to make a backup
// If the path we want is available we dont actually have to make a backup
if (!File.Exists(pathWant))
{
return true;
}
//delete any existing backup
// delete any existing backup
try
{
if (File.Exists(pathBackup))
{
File.Delete(pathBackup);
}
}
catch
{
//just give up on the whole thing in case of exceptions. pathWant will get overwritten by the caller.
// just give up on the whole thing in case of exceptions. pathWant will get overwritten by the caller.
return false;
}
//deletes are asynchronous, need to wait for it to be gone
// deletes are asynchronous, need to wait for it to be gone
if(!TryWaitForFileToVanish(pathBackup))
{
//gave up waiting for existing backup to be gone. the whole thing's a total loss
// gave up waiting for existing backup to be gone. the whole thing's a total loss
return false;
}
try
{
//actually move pathWant out of the way to pathBackup now that pathBackup is free
// actually move pathWant out of the way to pathBackup now that pathBackup is free
File.Move(pathWant, pathBackup);
}
catch
@ -78,8 +83,8 @@ namespace BizHawk.Common
return false;
}
//hmm these might be asynchronous too
//wait for the move to complete, at least enough for pathWant to be cleared up
// hmm these might be asynchronous too
// wait for the move to complete, at least enough for pathWant to be cleared up
return TryWaitForFileToVanish(pathWant);
}
@ -168,6 +173,7 @@ namespace BizHawk.Common
{
ret[i] = buf[i] != 0;
}
return ret;
}
@ -178,6 +184,7 @@ namespace BizHawk.Common
{
ret[i] = (byte)(buf[i] ? 1 : 0);
}
return ret;
}

View File

@ -16,6 +16,8 @@
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=StyleCop_002ESA1201/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=StyleCop_002ESA1202/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=StyleCop_002ESA1210/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ARGB/@EntryIndexedValue">ARGB</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CDL/@EntryIndexedValue">CDL</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DB/@EntryIndexedValue">DB</s:String></wpf:ResourceDictionary>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DB/@EntryIndexedValue">DB</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IO/@EntryIndexedValue">IO</s:String></wpf:ResourceDictionary>