// Copyright Microsoft Corporation.
// This source file is subject to the Microsoft Permissive License.
// See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.
// All other rights reserved.
using System;
using System.Diagnostics;
#if CCINamespace
using Microsoft.Cci.Metadata;
#else
using System.Compiler.Metadata;
#endif
using System.Globalization;
using System.Text;
#if CCINamespace
namespace Microsoft.Cci{
#else
namespace System.Compiler
{
#endif
#if !(FxCop || NoWriter)
/// <summary>
/// High performance replacement for System.IO.BinaryWriter.
/// </summary>
public sealed class BinaryWriter
{
public MemoryStream/*!*/ BaseStream;
private bool UTF8 = true;
public BinaryWriter(MemoryStream/*!*/ output)
{
this.BaseStream = output;
//^ base();
}
public BinaryWriter(MemoryStream/*!*/ output, Encoding/*!*/ encoding)
{
Debug.Assert(encoding == Encoding.Unicode);
this.BaseStream = output;
this.UTF8 = false;
//^ base();
}
public void Write(bool value)
{
MemoryStream m = this.BaseStream;
int i = m.Position;
m.Position = i + 1;
m.Buffer[i] = (byte)(value ? 1 : 0);
}
public void Write(byte value)
{
MemoryStream m = this.BaseStream;
int i = m.Position;
m.Position = i + 1;
m.Buffer[i] = value;
}
public void Write(sbyte value)
{
MemoryStream m = this.BaseStream;
int i = m.Position;
m.Position = i + 1;
m.Buffer[i] = (byte)value;
}
public void Write(byte[] buffer)
{
if (buffer == null) return;
this.BaseStream.Write(buffer, 0, buffer.Length);
}
public void Write(char ch)
{
MemoryStream m = this.BaseStream;
int i = m.Position;
if (this.UTF8)
{
if (ch < 0x80)
{
m.Position = i + 1;
m.Buffer[i] = (byte)ch;
}
else
this.Write(new char[] { ch });
}
else
{
m.Position = i + 2;
byte[] buffer = m.Buffer;
buffer[i++] = (byte)ch;
buffer[i] = (byte)(ch >> 8);
}
}
public void Write(char[] chars)
{
if (chars == null) return;
MemoryStream m = this.BaseStream;
int n = chars.Length;
int i = m.Position;
if (this.UTF8)
{
m.Position = i + n;
byte[] buffer = m.Buffer;
for (int j = 0; j < n; j++)
{
char ch = chars[j];
if ((ch & 0x80) != 0) goto writeUTF8;
buffer[i++] = (byte)ch;
}
return;
writeUTF8:
int ch32 = 0;
for (int j = n - (m.Position - i); j < n; j++)
{
char ch = chars[j];
if (ch < 0x80)
{
m.Position = i + 1;
buffer = m.Buffer;
buffer[i++] = (byte)ch;
}
else if (ch < 0x800)
{
m.Position = i + 2;
buffer = m.Buffer;
buffer[i++] = (byte)(((ch >> 6) & 0x1F) | 0xC0);
buffer[i] = (byte)((ch & 0x3F) | 0x80);
}
else if (0xD800 <= ch && ch <= 0xDBFF)
{
ch32 = (ch & 0x3FF) << 10;
}
else if (0xDC00 <= ch && ch <= 0xDFFF)
{
ch32 |= ch & 0x3FF;
m.Position = i + 4;
buffer = m.Buffer;
buffer[i++] = (byte)(((ch32 >> 18) & 0x7) | 0xF0);
buffer[i++] = (byte)(((ch32 >> 12) & 0x3F) | 0x80);
buffer[i++] = (byte)(((ch32 >> 6) & 0x3F) | 0x80);
buffer[i] = (byte)((ch32 & 0x3F) | 0x80);
}
else
{
m.Position = i + 3;
buffer = m.Buffer;
buffer[i++] = (byte)(((ch >> 12) & 0xF) | 0xE0);
buffer[i++] = (byte)(((ch >> 6) & 0x3F) | 0x80);
buffer[i] = (byte)((ch & 0x3F) | 0x80);
}
}
}
else
{
m.Position = i + n * 2;
byte[] buffer = m.Buffer;
for (int j = 0; j < n; j++)
{
char ch = chars[j];
buffer[i++] = (byte)ch;
buffer[i++] = (byte)(ch >> 8);
}
}
}
public unsafe void Write(double value)
{
MemoryStream m = this.BaseStream;
int i = m.Position;
m.Position = i + 8;
fixed (byte* b = m.Buffer)
*((double*)(b + i)) = value;
}
public void Write(short value)
{
MemoryStream m = this.BaseStream;
int i = m.Position;
m.Position = i + 2;
byte[] buffer = m.Buffer;
buffer[i++] = (byte)value;
buffer[i] = (byte)(value >> 8);
}
public unsafe void Write(ushort value)
{
MemoryStream m = this.BaseStream;
int i = m.Position;
m.Position = i + 2;
byte[] buffer = m.Buffer;
buffer[i++] = (byte)value;
buffer[i] = (byte)(value >> 8);
}
public void Write(int value)
{
MemoryStream m = this.BaseStream;
int i = m.Position;
m.Position = i + 4;
byte[] buffer = m.Buffer;
buffer[i++] = (byte)value;
buffer[i++] = (byte)(value >> 8);
buffer[i++] = (byte)(value >> 16);
buffer[i] = (byte)(value >> 24);
}
public void Write(uint value)
{
MemoryStream m = this.BaseStream;
int i = m.Position;
m.Position = i + 4;
byte[] buffer = m.Buffer;
buffer[i++] = (byte)value;
buffer[i++] = (byte)(value >> 8);
buffer[i++] = (byte)(value >> 16);
buffer[i] = (byte)(value >> 24);
}
public void Write(long value)
{
MemoryStream m = this.BaseStream;
int i = m.Position;
m.Position = i + 8;
byte[] buffer = m.Buffer;
uint lo = (uint)value;
uint hi = (uint)(value >> 32);
buffer[i++] = (byte)lo;
buffer[i++] = (byte)(lo >> 8);
buffer[i++] = (byte)(lo >> 16);
buffer[i++] = (byte)(lo >> 24);
buffer[i++] = (byte)hi;
buffer[i++] = (byte)(hi >> 8);
buffer[i++] = (byte)(hi >> 16);
buffer[i] = (byte)(hi >> 24);
}
public unsafe void Write(ulong value)
{
MemoryStream m = this.BaseStream;
int i = m.Position;
m.Position = i + 8;
byte[] buffer = m.Buffer;
uint lo = (uint)value;
uint hi = (uint)(value >> 32);
buffer[i++] = (byte)lo;
buffer[i++] = (byte)(lo >> 8);
buffer[i++] = (byte)(lo >> 16);
buffer[i++] = (byte)(lo >> 24);
buffer[i++] = (byte)hi;
buffer[i++] = (byte)(hi >> 8);
buffer[i++] = (byte)(hi >> 16);
buffer[i] = (byte)(hi >> 24);
}
public unsafe void Write(float value)
{
MemoryStream m = this.BaseStream;
int i = m.Position;
m.Position = i + 4;
fixed (byte* b = m.Buffer)
*((float*)(b + i)) = value;
}
public void Write(string str)
{
this.Write(str, false);
}
public void Write(string str, bool emitNullTerminator)
{
if (str == null)
{
Debug.Assert(!emitNullTerminator);
this.Write((byte)0xff);
return;
}
int n = str.Length;
if (!emitNullTerminator)
{
if (this.UTF8)
Ir2md.WriteCompressedInt(this, this.GetUTF8ByteCount(str));
else
Ir2md.WriteCompressedInt(this, n * 2);
}
MemoryStream m = this.BaseStream;
int i = m.Position;
if (this.UTF8)
{
m.Position = i + n;
byte[] buffer = m.Buffer;
for (int j = 0; j < n; j++)
{
char ch = str[j];
if (ch >= 0x80) goto writeUTF8;
buffer[i++] = (byte)ch;
}
if (emitNullTerminator)
{
m.Position = i + 1;
buffer = m.Buffer;
buffer[i] = 0;
}
return;
writeUTF8:
int ch32 = 0;
for (int j = n - (m.Position - i); j < n; j++)
{
char ch = str[j];
if (ch < 0x80)
{
m.Position = i + 1;
buffer = m.Buffer;
buffer[i++] = (byte)ch;
}
else if (ch < 0x800)
{
m.Position = i + 2;
buffer = m.Buffer;
buffer[i++] = (byte)(((ch >> 6) & 0x1F) | 0xC0);
buffer[i++] = (byte)((ch & 0x3F) | 0x80);
}
else if (0xD800 <= ch && ch <= 0xDBFF)
{
ch32 = (ch & 0x3FF) << 10;
}
else if (0xDC00 <= ch && ch <= 0xDFFF)
{
ch32 |= ch & 0x3FF;
m.Position = i + 4;
buffer = m.Buffer;
buffer[i++] = (byte)(((ch32 >> 18) & 0x7) | 0xF0);
buffer[i++] = (byte)(((ch32 >> 12) & 0x3F) | 0x80);
buffer[i++] = (byte)(((ch32 >> 6) & 0x3F) | 0x80);
buffer[i++] = (byte)((ch32 & 0x3F) | 0x80);
}
else
{
m.Position = i + 3;
buffer = m.Buffer;
buffer[i++] = (byte)(((ch >> 12) & 0xF) | 0xE0);
buffer[i++] = (byte)(((ch >> 6) & 0x3F) | 0x80);
buffer[i++] = (byte)((ch & 0x3F) | 0x80);
}
}
if (emitNullTerminator)
{
m.Position = i + 1;
buffer = m.Buffer;
buffer[i] = 0;
}
}
else
{
m.Position = i + n * 2;
byte[] buffer = m.Buffer;
for (int j = 0; j < n; j++)
{
char ch = str[j];
buffer[i++] = (byte)ch;
buffer[i++] = (byte)(ch >> 8);
}
if (emitNullTerminator)
{
m.Position = i + 2;
buffer = m.Buffer;
buffer[i++] = 0;
buffer[i] = 0;
}
}
}
public int GetUTF8ByteCount(string str)
{
int count = 0;
for (int i = 0, n = str == null ? 0 : str.Length; i < n; i++)
{
//^ assume str != null;
char ch = str[i];
if (ch < 0x80)
{
count += 1;
}
else if (ch < 0x800)
{
count += 2;
}
else if (0xD800 <= ch && ch <= 0xDBFF)
{
count += 2;
}
else if (0xDC00 <= ch && ch <= 0xDFFF)
{
count += 2;
}
else
{
count += 3;
}
}
return count;
}
}
public sealed class MemoryStream
{
public byte[]/* ! */ Buffer;
public int Length;
public int position;
public int Position
{
get { return this.position; }
set
{
byte[] myBuffer = this.Buffer;
int n = myBuffer.Length;
if (value >= n) this.Grow(myBuffer, n, value);
if (value > this.Length) this.Length = value;
this.position = value;
}
}
public MemoryStream()
{
this.Buffer = new byte[64];
this.Length = 0;
this.position = 0;
//^ base();
}
public MemoryStream(byte[]/*!*/ bytes)
{
if (bytes == null) { Debug.Fail(""); }
this.Buffer = bytes;
this.Length = bytes.Length;
this.position = 0;
//^ base();
}
private void Grow(byte[]/*!*/ myBuffer, int n, int m)
{
if (myBuffer == null) { Debug.Fail(""); return; }
int n2 = n * 2;
while (m >= n2) n2 = n2 * 2;
byte[] newBuffer = this.Buffer = new byte[n2];
for (int i = 0; i < n; i++)
newBuffer[i] = myBuffer[i]; //TODO: optimize this
}
public void Seek(long offset, SeekOrigin loc)
{
Debug.Assert(loc == SeekOrigin.Begin);
Debug.Assert(offset <= int.MaxValue);
this.Position = (int)offset;
}
public byte[]/*!*/ ToArray()
{
int n = this.Length;
byte[] source = this.Buffer;
if (source.Length == n) return this.Buffer; //unlikely, but the check is cheap
byte[] result = new byte[n];
for (int i = 0; i < n; i++)
result[i] = source[i]; //TODO: optimize this
return result;
}
public void Write(byte[]/*!*/ buffer, int index, int count)
{
int p = this.position;
this.Position = p + count;
byte[] myBuffer = this.Buffer;
for (int i = 0, j = p, k = index; i < count; i++)
myBuffer[j++] = buffer[k++]; //TODO: optimize this
}
public void WriteTo(MemoryStream/*!*/ stream)
{
stream.Write(this.Buffer, 0, this.Length);
}
public void WriteTo(System.IO.Stream/*!*/ stream)
{
stream.Write(this.Buffer, 0, this.Length);
}
}
public enum SeekOrigin { Begin, Current, End }
#endif
/// <summary>
/// A version of System.IO.Path that does not throw exceptions.
/// </summary>
#if FxCop || NoWriter
internal sealed class BetterPath {
#else
public sealed class BetterPath
{
#endif
public static readonly char AltDirectorySeparatorChar = System.IO.Path.AltDirectorySeparatorChar;
public static readonly char DirectorySeparatorChar = System.IO.Path.DirectorySeparatorChar;
public static readonly char VolumeSeparatorChar = System.IO.Path.VolumeSeparatorChar;
public static string ChangeExtension(string path, string extension)
{
if (path == null) return null;
string text1 = path;
int num1 = path.Length;
while (--num1 >= 0)
{
char ch1 = path[num1];
if (ch1 == '.')
{
text1 = path.Substring(0, num1);
break;
}
if (((ch1 == BetterPath.DirectorySeparatorChar) || (ch1 == BetterPath.AltDirectorySeparatorChar)) || (ch1 == BetterPath.VolumeSeparatorChar))
break;
}
if (extension == null || path.Length == 0) return text1;
if (extension.Length == 0 || extension[0] != '.')
text1 = text1 + ".";
return text1 + extension;
}
public static string Combine(string path1, string path2)
{
if (path1 == null || path1.Length == 0) return path2;
if (path2 == null || path2.Length == 0) return path1;
char ch = path2[0];
if (ch == BetterPath.DirectorySeparatorChar || ch == BetterPath.AltDirectorySeparatorChar || (path2.Length >= 2 && path2[1] == BetterPath.VolumeSeparatorChar))
return path2;
ch = path1[path1.Length - 1];
if (ch != BetterPath.DirectorySeparatorChar && ch != BetterPath.AltDirectorySeparatorChar && ch != BetterPath.VolumeSeparatorChar)
return (path1 + BetterPath.DirectorySeparatorChar + path2);
return path1 + path2;
}
public static string GetExtension(string path)
{
if (path == null) return null;
int length = path.Length;
for (int i = length; --i >= 0; )
{
char ch = path[i];
if (ch == '.')
{
if (i != length - 1)
return path.Substring(i, length - i);
else
return String.Empty;
}
if (ch == BetterPath.DirectorySeparatorChar || ch == BetterPath.AltDirectorySeparatorChar || ch == BetterPath.VolumeSeparatorChar)
break;
}
return string.Empty;
}
public static String GetFileName(string path)
{
if (path == null) return null;
int length = path.Length;
for (int i = length; --i >= 0; )
{
char ch = path[i];
if (ch == BetterPath.DirectorySeparatorChar || ch == BetterPath.AltDirectorySeparatorChar || ch == BetterPath.VolumeSeparatorChar)
return path.Substring(i + 1);
}
return path;
}
public static string GetFileNameWithoutExtension(string path)
{
int num1;
path = BetterPath.GetFileName(path);
if (path == null) return null;
if ((num1 = path.LastIndexOf('.')) == -1) return path;
return path.Substring(0, num1);
}
public static String GetDirectoryName(string path)
{
if (path == null) return null;
int length = path.Length;
for (int i = length; --i >= 0; )
{
char ch = path[i];
if (ch == BetterPath.DirectorySeparatorChar || ch == BetterPath.AltDirectorySeparatorChar || ch == BetterPath.VolumeSeparatorChar)
return path.Substring(0, i);
}
return path;
}
public static char[] GetInvalidFileNameChars()
{
#if WHIDBEY
return System.IO.Path.GetInvalidFileNameChars();
#else
return System.IO.Path.InvalidPathChars;
#endif
}
public static char[] GetInvalidPathChars()
{
#if WHIDBEY
return System.IO.Path.GetInvalidPathChars();
#else
return System.IO.Path.InvalidPathChars;
#endif
}
public static string GetTempFileName()
{
return System.IO.Path.GetTempFileName();
}
public static bool HasExtension(string path)
{
if (path != null)
{
int num1 = path.Length;
while (--num1 >= 0)
{
char ch1 = path[num1];
if (ch1 == '.')
{
if (num1 != (path.Length - 1))
{
return true;
}
return false;
}
if (((ch1 == BetterPath.DirectorySeparatorChar) || (ch1 == BetterPath.AltDirectorySeparatorChar)) || (ch1 == BetterPath.VolumeSeparatorChar))
{
break;
}
}
}
return false;
}
}
}
|