using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
namespace miew.IO
{
using String = System.String;
public static class File
{
static public String Read(string szfile)
{
String ret = String.Empty;
try
{
using (FileStream fs = System.IO.File.Open(szfile, FileMode.Open, FileAccess.Read, FileShare.Read))
{
// ?? manually detect BOM, because can't seem to set default encoding to 874 using 'detect from BOM' feature of StreamReader constructor
byte[] BOM = new byte[4];
fs.Read(BOM, 0, 4);
fs.Seek(0, SeekOrigin.Begin);
if ((BOM[0] == 0xef && BOM[1] == 0xbb && BOM[2] == 0xbf) || // UTF-8
(BOM[0] == 0xFE && BOM[1] == 0xFF) || // Unicode (Big-Endian)
(BOM[0] == 0xFF && BOM[1] == 0xFE) || // Unicode (Little-Endian)
(BOM[0] == 0 && BOM[1] == 0 && BOM[2] == 0xfe && BOM[3] == 0xff) || // UTF-32
(BOM[0] == 0x2b && BOM[1] == 0x2f && BOM[2] == 0x76)) // UTF-7
{
using (StreamReader sr = new StreamReader(fs, true)) // (auto-detect BOM)
ret = sr.ReadToEnd();
}
else
using (StreamReader sr = new StreamReader(fs /*, Encoding.Default */))
ret = sr.ReadToEnd();
}
}
catch (FileNotFoundException fnf)
{
Console.WriteLine("File not found: {0}", fnf.FileName);
Environment.Exit(1);
}
return ret;
}
/// <summary>
/// Case-insensitive search for a file
/// </summary>
static public String CaseInsensitiveFilename(String s_dir, String file)
{
return Directory.EnumerateFiles(s_dir, "*", SearchOption.TopDirectoryOnly)
.FirstOrDefault(f => Path.GetFileName(f).ToLower() == file);
}
};
public static class Extensions
{
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static IEnumerable<String> Lines(this TextReader tr)
{
String l;
while ((l = tr.ReadLine()) != null)
yield return l;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static Guid ReadGuid(this BinaryReader br)
{
return new Guid(br.ReadBytes(16));
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// Forces unicode encoding, as opposed to the BinaryReader default
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static String ReadUnicodeString(this BinaryReader br)
{
ushort cch = br.ReadUInt16();
if (cch == 0)
return String.Empty;
return new String(br.ReadChars(cch));
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static DateTime ReadSystemTime(this BinaryReader br)
{
return DateTime.FromBinary(br.ReadInt64());
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static void Write(this BinaryWriter bw, Guid guid)
{
bw.Write(guid.ToByteArray());
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static void WriteUnicodeString(this BinaryWriter bw, String s)
{
if (String.IsNullOrEmpty(s))
{
bw.Write((ushort)0);
return;
}
bw.Write((ushort)s.Length);
bw.Write(s.ToCharArray(), 0, s.Length);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static void Write(this BinaryWriter bw, DateTime dt)
{
bw.Write(dt.ToBinary());
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static void Write67EncodedUint(this BinaryWriter bw, uint i)
{
if (miew.BitArray.Extensions.OnesCount(i) == 1)
{
bw.Write((byte)(0x80 | miew.BitArray.Extensions.OnlyBitPosition(i)));
}
else
{
byte b = (byte)(i & 0x3F);
i >>= 6;
if (i == 0)
bw.Write(b);
else
{
bw.Write((byte)(0x40 | b));
while (true)
{
b = (byte)(i & 0x7F);
i >>= 7;
if (i == 0)
{
bw.Write(b);
break;
}
bw.Write((byte)(0x80 | b));
}
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static uint Read67EncodedUint(this BinaryReader br)
{
byte b = br.ReadByte();
if ((b & 0x80) > 0)
return (uint)1 << (b & 0x1F);
uint i = (uint)(b & 0x3F);
if ((b & 0x40) == 0)
return i;
int r = 6;
while (true)
{
b = br.ReadByte();
i |= (uint)(b & 0x7F) << r;
if ((b & 0x80) == 0)
return i;
r += 7;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// Write the specified thin string to the memory stream
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static void WriteStringAsByteArr(this MemoryStream ms, String thin)
{
Byte[] buf = miew.String.Thin.Extensions.ToByteArr(thin);
ms.Write(buf);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// Image a portion of the specified string to the memory stream in little-endian Unicode byte order,
/// without creating an intermediate string object. However, Stringbuilder(String, int, int) is faster than this.
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static unsafe void Write(this MemoryStream ms, String s, int index, int length)
{
if (index < 0 || index + length >= s.Length)
throw new ArgumentException();
long idx = ms.Position;
int cb = length * sizeof(Char);
ms.Position = idx + cb;
ms.SetLength(ms.Position);
fixed (Char* p = s)
{
IntPtr ip = new IntPtr(p + index);
Marshal.Copy(ip, ms.GetBuffer(), (int)idx, cb);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static void Write(this Stream str, Byte[] buf)
{
str.Write(buf, 0, buf.Length);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static void AlignQword(this Stream str)
{
long pos = str.Position;
long p2 = (pos + 7) & ~7;
if (p2 != pos)
{
if (str.Length <= p2)
str.Write(new byte[8 - (pos & 7)]);
else
str.Seek(p2, SeekOrigin.Begin);
}
}
}
}