diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2009-09-20 21:18:59 -0700 |
---|---|---|
committer | Andrew Arnott <andrewarnott@gmail.com> | 2009-09-21 08:06:22 -0700 |
commit | bbe3f9cc9c8a1e5909273c1a162a63ea7a66afd8 (patch) | |
tree | c91f66e642c4d26fca266e226b3f2765f546d700 /tools/Sandcastle/Source/CCI/MemoryMappedFile.cs | |
parent | 627014f0bbc3fd576277375e70f8391d150b0a67 (diff) | |
download | DotNetOpenAuth-bbe3f9cc9c8a1e5909273c1a162a63ea7a66afd8.zip DotNetOpenAuth-bbe3f9cc9c8a1e5909273c1a162a63ea7a66afd8.tar.gz DotNetOpenAuth-bbe3f9cc9c8a1e5909273c1a162a63ea7a66afd8.tar.bz2 |
Switched out the Sandcastle binaries for the source code.
Diffstat (limited to 'tools/Sandcastle/Source/CCI/MemoryMappedFile.cs')
-rw-r--r-- | tools/Sandcastle/Source/CCI/MemoryMappedFile.cs | 459 |
1 files changed, 459 insertions, 0 deletions
diff --git a/tools/Sandcastle/Source/CCI/MemoryMappedFile.cs b/tools/Sandcastle/Source/CCI/MemoryMappedFile.cs new file mode 100644 index 0000000..ac9558c --- /dev/null +++ b/tools/Sandcastle/Source/CCI/MemoryMappedFile.cs @@ -0,0 +1,459 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// +using System; +#if CCINamespace +using Microsoft.Cci; +#else +using System.Compiler; +#endif +using System.Diagnostics; +using System.IO; +using System.Globalization; +using System.Runtime.InteropServices; +using System.Text; + +#if CCINamespace +namespace Microsoft.Cci.Metadata{ +#else +namespace System.Compiler.Metadata +{ +#endif + unsafe internal sealed class MemoryCursor + { + private byte* buffer, pb; + readonly internal int Length; + +#if !ROTOR + internal MemoryCursor(MemoryMappedFile/*!*/ memoryMap) + : this(memoryMap.Buffer, memoryMap.Length) + { + } +#endif + internal MemoryCursor(byte* buffer, int length, int position) + { + this.buffer = buffer; + this.pb = buffer + position; + this.Length = length; + } + internal MemoryCursor(byte* buffer, int length) + : this(buffer, length, 0) + { + } + internal MemoryCursor(MemoryCursor/*!*/ c) + { + this.buffer = c.buffer; + this.pb = c.pb; + this.Length = c.Length; + } + + internal byte* GetBuffer() + { + return this.buffer; + } + + internal int Position + { + get { return (int)(this.pb - this.buffer); } + set { this.pb = this.buffer + value; } + } + internal void Align(int size) + { + Debug.Assert(size == 2 || size == 4 || size == 8 || size == 16 || size == 32 || size == 64); + int remainder = Position & (size - 1); + if (remainder != 0) + pb += size - remainder; + } + + //internal System.Char Char(int i){ return *(System.Char*)(this.pb+i*sizeof(System.Char)); } + //internal System.SByte SByte(int i){ return *(System.SByte*)(this.pb+i*sizeof(System.SByte)); } + internal System.Int16 Int16(int i) { return *(System.Int16*)(this.pb + i * sizeof(System.Int16)); } + internal System.Int32 Int32(int i) { return *(System.Int32*)(this.pb + i * sizeof(System.Int32)); } + //internal System.Int64 Int64(int i){ return *(System.Int64*)(this.pb+i*sizeof(System.Int64)); } + internal System.Byte Byte(int i) { return *(System.Byte*)(this.pb + i * sizeof(System.Byte)); } + internal System.UInt16 UInt16(int i) { return *(System.UInt16*)(this.pb + i * sizeof(System.UInt16)); } + //internal System.UInt32 UInt32(int i){ return *(System.UInt32*)(this.pb+i*sizeof(System.UInt32)); } + //internal System.UInt64 UInt64(int i){ return *(System.UInt64*)(this.pb+i*sizeof(System.UInt64)); } + //internal System.Boolean Boolean(int i){ return *(System.Boolean*)(this.pb+i*sizeof(System.Boolean)); } + //internal System.Single Single(int i){ return *(System.Single*)(this.pb+i*sizeof(System.Single)); } + //internal System.Double Double(int i){ return *(System.Double*)(this.pb+i*sizeof(System.Double)); } + + //internal void SkipChar(int c){ this.pb += c*sizeof(System.Char); } + //internal void SkipSByte(int c){ this.pb += c*sizeof(System.SByte); } + internal void SkipInt16(int c) { this.pb += c * sizeof(System.Int16); } + internal void SkipInt32(int c) { this.pb += c * sizeof(System.Int32); } + //internal void SkipInt64(int c){ this.pb += c*sizeof(System.Int64); } + internal void SkipByte(int c) { this.pb += c * sizeof(System.Byte); } + internal void SkipUInt16(int c) { this.pb += c * sizeof(System.UInt16); } + //internal void SkipUInt32(int c){ this.pb += c*sizeof(System.UInt32); } + //internal void SkipUInt64(int c){ this.pb += c*sizeof(System.UInt64); } + //internal void SkipBoolean(int c){ this.pb += c*sizeof(System.Boolean); } + //internal void SkipSingle(int c){ this.pb += c*sizeof(System.Single); } + //internal void SkipDouble(int c){ this.pb += c*sizeof(System.Double); } + + internal System.Char ReadChar() { byte* pb = this.pb; System.Char v = *(System.Char*)pb; this.pb = pb + sizeof(System.Char); return v; } + internal System.SByte ReadSByte() { byte* pb = this.pb; System.SByte v = *(System.SByte*)pb; this.pb = pb + sizeof(System.SByte); return v; } + internal System.Int16 ReadInt16() { byte* pb = this.pb; System.Int16 v = *(System.Int16*)pb; this.pb = pb + sizeof(System.Int16); return v; } + internal System.Int32 ReadInt32() { byte* pb = this.pb; System.Int32 v = *(System.Int32*)pb; this.pb = pb + sizeof(System.Int32); return v; } + internal System.Int64 ReadInt64() { byte* pb = this.pb; System.Int64 v = *(System.Int64*)pb; this.pb = pb + sizeof(System.Int64); return v; } + internal System.Byte ReadByte() { byte* pb = this.pb; System.Byte v = *(System.Byte*)pb; this.pb = pb + sizeof(System.Byte); return v; } + internal System.UInt16 ReadUInt16() { byte* pb = this.pb; System.UInt16 v = *(System.UInt16*)pb; this.pb = pb + sizeof(System.UInt16); return v; } + internal System.UInt32 ReadUInt32() { byte* pb = this.pb; System.UInt32 v = *(System.UInt32*)pb; this.pb = pb + sizeof(System.UInt32); return v; } + internal System.UInt64 ReadUInt64() { byte* pb = this.pb; System.UInt64 v = *(System.UInt64*)pb; this.pb = pb + sizeof(System.UInt64); return v; } + internal System.Boolean ReadBoolean() { byte* pb = this.pb; System.Boolean v = *(System.Boolean*)pb; this.pb = pb + sizeof(System.Boolean); return v; } + internal System.Single ReadSingle() { byte* pb = this.pb; System.Single v = *(System.Single*)pb; this.pb = pb + sizeof(System.Single); return v; } + internal System.Double ReadDouble() { byte* pb = this.pb; System.Double v = *(System.Double*)pb; this.pb = pb + sizeof(System.Double); return v; } + + internal System.Int32 ReadReference(int refSize) + { + if (refSize == 2) return ReadUInt16(); + return ReadInt32(); + } + + internal int ReadCompressedInt() + { + byte headerByte = ReadByte(); + int result; + if ((headerByte & 0x80) == 0x00) + result = headerByte; + else if ((headerByte & 0x40) == 0x00) + result = ((headerByte & 0x3f) << 8) | ReadByte(); + else if (headerByte == 0xFF) + result = -1; + else + result = ((headerByte & 0x3f) << 24) | (ReadByte() << 16) | (ReadByte() << 8) | ReadByte(); + return result; + } + + internal byte[]/*!*/ ReadBytes(int c) + { + byte[] result = new byte[c]; + byte* pb = this.pb; + for (int i = 0; i < c; i++) + result[i] = *pb++; + this.pb = pb; + return result; + } + + internal unsafe Identifier/*!*/ ReadIdentifierFromSerString() + { + byte* pb = this.pb; + byte headerByte = *pb++; + uint length = 0; + if ((headerByte & 0x80) == 0x00) + length = headerByte; + else if ((headerByte & 0x40) == 0x00) + length = (uint)((headerByte & 0x3f) << 8) | *pb++; + else + length = (uint)((headerByte & 0x3f) << 24) | (uint)(*pb++ << 16) | (uint)(*pb++ << 8) | (*pb++); + this.pb = pb + length; + return Identifier.For(pb, length/*, this.KeepAlive*/); + } + + internal string/*!*/ ReadUTF8(int bytesToRead) + { + char[] buffer = new char[bytesToRead]; + byte* pb = this.pb; + this.pb += bytesToRead; + int j = 0; + while (bytesToRead > 0) + { + byte b = *pb++; bytesToRead--; + if ((b & 0x80) == 0 || bytesToRead == 0) + { + buffer[j++] = (char)b; + continue; + } + char ch; + byte b1 = *pb++; bytesToRead--; + if ((b & 0x20) == 0) + ch = (char)(((b & 0x1F) << 6) | (b1 & 0x3F)); + else + { + if (bytesToRead == 0) + { //Dangling lead bytes, do not decompose + buffer[j++] = (char)((b << 8) | b1); + break; + } + byte b2 = *pb++; bytesToRead--; + uint ch32; + if ((b & 0x10) == 0) + ch32 = (uint)(((b & 0x0F) << 12) | ((b1 & 0x3F) << 6) | (b2 & 0x3F)); + else + { + if (bytesToRead == 0) + { //Dangling lead bytes, do not decompose + buffer[j++] = (char)((b << 8) | b1); + buffer[j++] = (char)b2; + break; + } + byte b3 = *pb++; bytesToRead--; + ch32 = (uint)(((b & 0x07) << 18) | ((b1 & 0x3F) << 12) | ((b2 & 0x3F) << 6) | (b3 & 0x3F)); + } + if ((ch32 & 0xFFFF0000) == 0) + ch = (char)ch32; + else + { //break up into UTF16 surrogate pair + buffer[j++] = (char)((ch32 >> 10) | 0xD800); + ch = (char)((ch32 & 0x3FF) | 0xDC00); + } + } + buffer[j++] = ch; + } + if (j > 0 && buffer[j - 1] == 0) j--; + return new String(buffer, 0, j); + } + + internal string/*!*/ ReadUTF8() + { + byte* pb = this.pb; + StringBuilder sb = new StringBuilder(); + byte b = 0; + for (; ; ) + { + b = *pb++; + if (b == 0) break; + if ((b & 0x80) == 0) + { + sb.Append((char)b); + continue; + } + char ch; + byte b1 = *pb++; + if (b1 == 0) + { //Dangling lead byte, do not decompose + sb.Append((char)b); + break; + } + if ((b & 0x20) == 0) + { + ch = (char)(((b & 0x1F) << 6) | (b1 & 0x3F)); + } + else + { + byte b2 = *pb++; + if (b2 == 0) + { //Dangling lead bytes, do not decompose + sb.Append((char)((b << 8) | b1)); + break; + } + uint ch32; + if ((b & 0x10) == 0) + ch32 = (uint)(((b & 0x0F) << 12) | ((b1 & 0x3F) << 6) | (b2 & 0x3F)); + else + { + byte b3 = *pb++; + if (b3 == 0) + { //Dangling lead bytes, do not decompose + sb.Append((char)((b << 8) | b1)); + sb.Append((char)b2); + break; + } + ch32 = (uint)(((b & 0x07) << 18) | ((b1 & 0x3F) << 12) | ((b2 & 0x3F) << 6) | (b3 & 0x3F)); + } + if ((ch32 & 0xFFFF0000) == 0) + ch = (char)ch32; + else + { //break up into UTF16 surrogate pair + sb.Append((char)((ch32 >> 10) | 0xD800)); + ch = (char)((ch32 & 0x3FF) | 0xDC00); + } + } + sb.Append(ch); + } + this.pb = pb; + return sb.ToString(); + } + + internal string/*!*/ ReadUTF16(int charsToRead) + { + char* pc = (char*)this.pb; + char[] buffer = new char[charsToRead]; + for (int i = 0; i < charsToRead; i++) + buffer[i] = *pc++; + this.pb = (byte*)pc; + return new String(buffer, 0, charsToRead); + } + + internal string/*!*/ ReadUTF16() + { + string result = new string((char*)this.pb); + this.pb += (result.Length + 1) * 2; + return result; + } + + internal string/*!*/ ReadASCII(int bytesToRead) + { + int c = bytesToRead; + if (bytesToRead == -1) c = 128; //buffer size + byte* pb = this.pb; + char[] buffer = new char[c]; + int j = 0; + byte b = 0; + Restart: + while (j < c) + { + b = *pb++; + if (b == 0) break; + buffer[j++] = (char)b; + } + if (bytesToRead == -1) + { + if (b != 0) + { + char[] newBuffer = new char[c *= 2]; + for (int copy = 0; copy < j; copy++) + newBuffer[copy] = buffer[copy]; + buffer = newBuffer; + goto Restart; + } + this.pb = pb; + } + else + this.pb += bytesToRead; + return new String(buffer, 0, j); + } + + internal string/*!*/ ReadASCII() { return ReadASCII(-1); } + } + +#if !ROTOR +#if !FxCop + /// <summary> + /// Public only for use by the Framework. Do not use this class. + /// Well, if you really really must, use it only if you can tolerate keeping the file locked for at least as long as any Identifier + /// derived from the file stays alive. + /// </summary> + unsafe public sealed class MemoryMappedFile : IDisposable, ISourceTextBuffer + { +#else + unsafe sealed class MemoryMappedFile : IDisposable{ +#endif + private byte* buffer; + private int length; + + public MemoryMappedFile(string fileName) + { + this.OpenMap(fileName); + } + ~MemoryMappedFile() + { + this.CloseMap(); + } + public void Dispose() + { + this.CloseMap(); + GC.SuppressFinalize(this); + } + + public byte* Buffer + { + get + { + Debug.Assert(this.buffer != null); + return this.buffer; + } + } + public int Length + { + get + { + Debug.Assert(this.buffer != null); + return this.length; + } + } +#if !FxCop + string ISourceText.Substring(int start, int length) + { + Debug.Assert(false, "Can't use Substring on memory mapped files"); + return null; + } + char ISourceText.this[int index] + { + get + { + Debug.Assert(false, "Can't access memory mapped files via an indexer, use Buffer"); + return ' '; + } + } +#endif + private void OpenMap(string filename) + { + IntPtr hmap; + int length; + using (FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + if (stream.Length > Int32.MaxValue) + throw new FileLoadException(ExceptionStrings.FileTooBig, filename); + length = unchecked((int)stream.Length); +#if WHIDBEY && !OldWhidbey + hmap = CreateFileMapping(stream.SafeFileHandle.DangerousGetHandle(), IntPtr.Zero, PageAccess.PAGE_READONLY, 0, length, null); +#else + hmap = CreateFileMapping(stream.Handle, IntPtr.Zero, PageAccess.PAGE_READONLY, 0, length, null); +#endif + if (hmap == IntPtr.Zero) + { + int rc = Marshal.GetLastWin32Error(); + throw new FileLoadException(String.Format(CultureInfo.CurrentCulture, + ExceptionStrings.CreateFileMappingReturnedErrorCode, rc.ToString()), filename); + } + } + this.buffer = (byte*)MapViewOfFile(hmap, FileMapAccess.FILE_MAP_READ, 0, 0, (IntPtr)length); + MemoryMappedFile.CloseHandle(hmap); + if (this.buffer == null) + { + int rc = Marshal.GetLastWin32Error(); + throw new FileLoadException(String.Format(CultureInfo.CurrentCulture, + ExceptionStrings.MapViewOfFileReturnedErrorCode, rc.ToString()), filename); + } + this.length = length; + } + private void CloseMap() + { + if (buffer != null) + { + UnmapViewOfFile(buffer); + buffer = null; + } + } +#if !FxCop + void ISourceText.MakeCollectible() + { + } +#endif + + private enum PageAccess : int { PAGE_READONLY = 0x02 }; + private enum FileMapAccess : int { FILE_MAP_READ = 0x0004 }; + + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + private static extern IntPtr CreateFileMapping( + IntPtr hFile, // handle to file + IntPtr lpAttributes, // security + PageAccess flProtect, // protection + int dwMaximumSizeHigh, // high-order DWORD of size + int dwMaximumSizeLow, // low-order DWORD of size + string lpName // object name + ); + + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + private static extern void* MapViewOfFile( + IntPtr hFileMappingObject, // handle to file-mapping object + FileMapAccess dwDesiredAccess, // access mode + int dwFileOffsetHigh, // high-order DWORD of offset + int dwFileOffsetLow, // low-order DWORD of offset + IntPtr dwNumberOfBytesToMap // number of bytes to map + ); + + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool UnmapViewOfFile( + void* lpBaseAddress // starting address + ); + + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool CloseHandle( + IntPtr hObject // handle to object + ); + } +#endif +} |