BizHawk/BizHawk.Common/Extensions/Extensions.cs

405 lines
9.5 KiB
C#

using System;
using System.Linq;
using System.Reflection;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
namespace BizHawk.Common
{
public static class Extensions
{
public static string GetDirectory(this Assembly asm)
{
string codeBase = asm.CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uri.Path);
return Path.GetDirectoryName(path);
}
public static int LowerBoundBinarySearch<T, TKey>(this IList<T> list, Func<T, TKey> keySelector, TKey key) where TKey : IComparable<TKey>
{
int min = 0;
int max = list.Count;
int mid;
TKey midKey;
while (min < max)
{
mid = (max + min) / 2;
T midItem = list[mid];
midKey = keySelector(midItem);
int comp = midKey.CompareTo(key);
if (comp < 0)
{
min = mid + 1;
}
else if (comp > 0)
{
max = mid - 1;
}
else
{
return mid;
}
}
//did we find it exactly?
if (min == max && keySelector(list[min]).CompareTo(key) == 0)
{
return min;
}
mid = min;
//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
if (mid == 0)
return -1; //had to go all the way to min before giving up; lower bound is min
midKey = keySelector(list[mid]);
if (midKey.CompareTo(key) >= 0) return mid - 1;
else return mid;
}
public static string ToHexString(this int n, int numdigits)
{
return String.Format("{0:X" + numdigits + "}", n);
}
public static string ToHexString(this uint n, int numdigits)
{
return String.Format("{0:X" + numdigits + "}", n);
}
public static string ToHexString(this byte n, int numdigits)
{
return String.Format("{0:X" + numdigits + "}", n);
}
public static string ToHexString(this ushort n, int numdigits)
{
return String.Format("{0:X" + numdigits + "}", n);
}
// http://stackoverflow.com/questions/1766328/can-linq-use-binary-search-when-the-collection-is-ordered
public static T BinarySearch<T, TKey>(this IList<T> list, Func<T, TKey> keySelector, TKey key)
where TKey : IComparable<TKey>
{
int min = 0;
int max = list.Count;
while (min < max)
{
int mid = (max + min) / 2;
T midItem = list[mid];
TKey midKey = keySelector(midItem);
int comp = midKey.CompareTo(key);
if (comp < 0)
{
min = mid + 1;
}
else if (comp > 0)
{
max = mid - 1;
}
else
{
return midItem;
}
}
if (min == max &&
keySelector(list[min]).CompareTo(key) == 0)
{
return list[min];
}
throw new InvalidOperationException("Item not found");
}
public static void CopyTo(this Stream src, Stream dest)
{
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);
}
public static void CopyTo(this MemoryStream src, Stream dest)
{
dest.Write(src.GetBuffer(), (int)src.Position, (int)(src.Length - src.Position));
}
public static void CopyTo(this Stream src, MemoryStream dest)
{
if (src.CanSeek)
{
int pos = (int)dest.Position;
int length = (int)(src.Length - src.Position) + pos;
dest.SetLength(length);
while (pos < length)
pos += src.Read(dest.GetBuffer(), pos, length - pos);
}
else
src.CopyTo(dest);
}
public static bool Bit(this byte b, int index)
{
return (b & (1 << index)) != 0;
}
public static bool Bit(this int b, int index)
{
return (b & (1 << index)) != 0;
}
public static bool Bit(this ushort b, int index)
{
return (b & (1 << index)) != 0;
}
public static bool In(this int i, params int[] options)
{
return options.Any(j => i == j);
}
public static bool ContainsStartsWith(this IEnumerable<string> options, string str)
{
return options.Any(opt => opt.StartsWith(str));
}
public static string GetOptionValue(this IEnumerable<string> options, string str)
{
try
{
foreach (string opt in options)
{
if (opt.StartsWith(str))
{
return opt.Split('=')[1];
}
}
}
catch (Exception) { }
return null;
}
public static void SaveAsHex(this byte[] buffer, TextWriter writer)
{
foreach (byte b in buffer)
{
writer.Write("{0:X2}", b);
}
writer.WriteLine();
}
public unsafe static void SaveAsHexFast(this byte[] buffer, TextWriter writer)
{
char* table = Util.HexConvPtr;
if (buffer.Length > 0)
{
int len = buffer.Length;
fixed (byte* src = &buffer[0])
for (int i = 0; i < len; i++)
{
writer.Write(table[src[i] >> 4]);
writer.Write(table[src[i] & 15]);
}
}
writer.WriteLine();
}
public static void SaveAsHex(this byte[] buffer, TextWriter writer, int length)
{
for (int i = 0; i < length; i++)
{
writer.Write("{0:X2}", buffer[i]);
}
writer.WriteLine();
}
public static void SaveAsHex(this short[] buffer, TextWriter writer)
{
foreach (short b in buffer)
{
writer.Write("{0:X4}", b);
}
writer.WriteLine();
}
public static void SaveAsHex(this ushort[] buffer, TextWriter writer)
{
foreach (ushort b in buffer)
{
writer.Write("{0:X4}", b);
}
writer.WriteLine();
}
public static void SaveAsHex(this int[] buffer, TextWriter writer)
{
foreach (int b in buffer)
{
writer.Write("{0:X8}", b);
}
writer.WriteLine();
}
public static void SaveAsHex(this uint[] buffer, TextWriter writer)
{
foreach (uint b in buffer)
{
writer.Write("{0:X8}", b);
}
writer.WriteLine();
}
public static void Write(this BinaryWriter bw, int[] buffer)
{
foreach (int b in buffer)
{
bw.Write(b);
}
}
public static void Write(this BinaryWriter bw, uint[] buffer)
{
foreach (uint b in buffer)
{
bw.Write(b);
}
}
public static void Write(this BinaryWriter bw, short[] buffer)
{
foreach (short b in buffer)
{
bw.Write(b);
}
}
public static void Write(this BinaryWriter bw, ushort[] buffer)
{
foreach (ushort t in buffer)
{
bw.Write(t);
}
}
public static int[] ReadInt32s(this BinaryReader br, int num)
{
int[] ret = new int[num];
for (int i = 0; i < num; i++)
{
ret[i] = br.ReadInt32();
}
return ret;
}
public static short[] ReadInt16s(this BinaryReader br, int num)
{
short[] ret = new short[num];
for (int i = 0; i < num; i++)
{
ret[i] = br.ReadInt16();
}
return ret;
}
public static ushort[] ReadUInt16s(this BinaryReader br, int num)
{
ushort[] ret = new ushort[num];
for (int i = 0; i < num; i++)
{
ret[i] = br.ReadUInt16();
}
return ret;
}
public static void ReadFromHex(this byte[] buffer, string hex)
{
if (hex.Length%2 != 0)
{
throw new Exception("Hex value string does not appear to be properly formatted.");
}
for (int i = 0; i < buffer.Length && i * 2 < hex.Length; i++)
{
string bytehex = "" + hex[i * 2] + hex[i * 2 + 1];
buffer[i] = byte.Parse(bytehex, NumberStyles.HexNumber);
}
}
private static int Hex2Int(char c)
{
if (c <= '9')
{
return c - '0';
}
else if (c <= 'F')
{
return c - '7';
}
else
{
return c - 'W';
}
}
public static void ReadFromHexFast(this byte[] buffer, string hex)
{
for (int i = 0; i < buffer.Length && i * 2 < hex.Length; i++)
{
buffer[i] = (byte)(Hex2Int(hex[i * 2]) * 16 + Hex2Int(hex[i * 2 + 1]));
}
}
public static void ReadFromHex(this short[] buffer, string hex)
{
if (hex.Length % 4 != 0)
throw new Exception("Hex value string does not appear to be properly formatted.");
for (int i = 0; i < buffer.Length && i * 4 < hex.Length; i++)
{
string shorthex = "" + hex[i * 4] + hex[(i * 4) + 1] + hex[(i * 4) + 2] + hex[(i * 4) + 3];
buffer[i] = short.Parse(shorthex, NumberStyles.HexNumber);
}
}
public static void ReadFromHex(this ushort[] buffer, string hex)
{
if (hex.Length % 4 != 0)
throw new Exception("Hex value string does not appear to be properly formatted.");
for (int i = 0; i < buffer.Length && i * 4 < hex.Length; i++)
{
string ushorthex = "" + hex[i * 4] + hex[(i * 4) + 1] + hex[(i * 4) + 2] + hex[(i * 4) + 3];
buffer[i] = ushort.Parse(ushorthex, NumberStyles.HexNumber);
}
}
public static void ReadFromHex(this int[] buffer, string hex)
{
if (hex.Length % 8 != 0)
{
throw new Exception("Hex value string does not appear to be properly formatted.");
}
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
string inthex = hex.Substring(i * 8, 8);
buffer[i] = int.Parse(inthex, NumberStyles.HexNumber);
}
}
//these don't work??? they dont get chosen by compiler
public static void WriteBit(this BinaryWriter bw, Bit bit) { bw.Write((bool)bit); }
public static Bit ReadBit(this BinaryReader br) { return br.ReadBoolean(); }
}
}