context: //-----------------------------------------------------------------------------
  //
  // Copyright (c) Microsoft. All rights reserved.
  // This code is licensed under the Microsoft Public License.
  // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
  // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
  // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
  // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
  //
  //-----------------------------------------------------------------------------
  using System;
  using System.IO;
  using System.Globalization;
  using System.Runtime.InteropServices;
  using System.Text;
  //^ using Microsoft.Contracts;
  
  
  //  Left over work items:
  //  1) Try to optimize String reading and writing methods
  
  #if !BIGENDIAN && !LITTLEENDIAN
  #error Either BIGENDIAN or LITTLEENDIAN must be defined.
  #endif
  
  namespace Microsoft.Cci.UtilityDataStructures {
    unsafe struct MemoryBlock {
      internal readonly byte* Buffer;
      internal readonly int Length;
      internal MemoryBlock(
        byte* buffer,
        int length
      ) {
        this.Buffer = buffer;
        this.Length = length;
      }
      internal MemoryBlock(
        byte* buffer,
        uint length
      ) {
        this.Buffer = buffer;
        this.Length = (int)length;
      }
    }
  
    unsafe internal struct MemoryReader {
      #region Fields
      //^ [SpecPublic]
      readonly byte* Buffer;
      //^ [SpecPublic]
      private byte* CurrentPointer;
      internal readonly int Length;
      // ^ invariant this.CurrentPointer >= this.Buffer;
      // ^ invariant this.CurrentPointer <= this.Buffer + this.Length;
      // ^ invariant this.Length > 0;
      // ^ invariant this.Buffer != null;
      // ^ invariant this.CurrentPointer != null;
      #endregion
  
      #region Constructors
      internal MemoryReader(
        byte* buffer,
        int length,
        int offset
      )
        //^ requires buffer != null;
        //^ requires offset <= length;
        //^ requires length > 0;
      {
        this.Buffer = buffer;
        this.CurrentPointer = buffer + offset;
        this.Length = length;
      }
  
      internal MemoryReader(
        byte* buffer,
        int length
      )
        : this(buffer, length, 0)
        //^ requires buffer != null;
        //^ requires length > 0;
      {
      }
      internal MemoryReader(
        byte* buffer,
        uint length
      )
        : this(buffer, (int)length, 0)
        //^ requires buffer != null;
        //^ requires length > 0;
      {
      }
      internal MemoryReader(
        MemoryBlock memBlock
      )
        : this(memBlock.Buffer, memBlock.Length, 0)
        //^ requires memBlock.IsValid;
      {
      }
      #endregion Constructors
  
      #region Offset, Skipping, Marking, Alignment
      internal uint Offset {
        get {
          return (uint)(this.CurrentPointer - this.Buffer);
        }
      }
      internal uint RemainingBytes {
        get {
          return (uint)(this.Length - (this.CurrentPointer - this.Buffer));
        }
      }
      internal bool NotEndOfBytes {
        get {
          return this.Length > (int)(this.CurrentPointer - this.Buffer);
        }
      }
      internal bool SeekOffset(
        int offset
      ) {
        if (offset >= this.Length)
          return false;
        this.CurrentPointer = this.Buffer + offset;
        return true;
      }
      //^ bool EnsureOffsetRange(
      //^   int offset,
      //^   int byteCount
      //^ )
      //^   //^ ensures result == this.Offset + byteCount <= this.Length;
      //^ {
      //^   return this.Offset + offset + byteCount <= this.Length;
      //^ }
      internal void SkipBytes(
        int count
      ) {
        this.CurrentPointer += count;
      }
      internal void Align(
        uint alignment
      )
        //^ requires alignment == 2 || alignment == 4 || alignment == 8 || alignment == 16 || alignment == 32 || alignment == 64;
      {
        uint remainder = this.Offset & (alignment - 1);
        if (remainder != 0)
          this.CurrentPointer += alignment - remainder;
      }
      internal MemoryBlock RemainingMemoryBlock {
        get {
          return new MemoryBlock(this.CurrentPointer, this.RemainingBytes);
        }
      }
      internal MemoryBlock GetMemoryBlockAt(
        uint offset,
        uint length
      )
        //^ requires this.CurrentPointer - this.Buffer + offset + length <= this.Length;
      {
        return new MemoryBlock(this.CurrentPointer + offset, length);
      }
      internal MemoryBlock GetMemoryBlockAt(
        int offset,
        int length
      )
        //^ requires this.CurrentPointer - this.Buffer + offset + length <= this.Length;
      {
        return new MemoryBlock(this.CurrentPointer + offset, length);
      }
      #endregion Offsets, Skipping, Marking, Alignment
  
      #region Peek Methods
  
      internal Int16 PeekInt16(
        int offset
      ) {
  #if COMPACTFX
        if ((int)(this.CurrentPointer + offset) % 2 != 0) return UnalignedPeekInt16(offset);
  #endif
  #if LITTLEENDIAN
        return *(Int16*)(this.CurrentPointer + offset);
  #elif BIGENDIAN
        ushort ush = *(ushort*)(this.CurrentPointer + offset);
        return (Int16)((ush << 8) | (ush >> 8));
  #endif
      }
  
      internal Int32 PeekInt32(
        int offset
      ) {
  #if COMPACTFX
        if ((int)(this.CurrentPointer + offset) % 4 != 0) return UnalignedPeekInt32(offset);
  #endif
  #if LITTLEENDIAN
        return *(Int32*)(this.CurrentPointer + offset);
  #elif BIGENDIAN
        uint uin = *(uint*)(this.CurrentPointer + offset);//1234
        uin = (uin >> 16) | (uin << 16); //3412
        uin = ((uin & 0xFF00FF00) >> 8) | ((uin & 0x00FF00FF) << 8); //0301 | 4020 == 4321
        return (Int32)uin;
  #endif
      }
  
      internal Byte PeekByte(
        int offset
      ) {
        return *(Byte*)(this.CurrentPointer + offset);
      }
  
      internal UInt16 PeekUInt16(
        int offset
      ) {
  #if COMPACTFX
        if ((int)(this.CurrentPointer + offset) % 2 != 0) return UnalignedPeekUInt16(offset);
  #endif
  #if LITTLEENDIAN
        return *(UInt16*)(this.CurrentPointer + offset);
  #elif BIGENDIAN
        ushort ush = *(ushort*)(this.CurrentPointer + offset);
        return (UInt16)((ush << 8) | (ush >> 8));
  #endif
      }
  
      internal UInt16 PeekUInt16(
        uint offset
      ) {
  #if COMPACTFX
        if ((int)(this.CurrentPointer + offset) % 2 != 0) return UnalignedPeekUInt16(offset);
  #endif
  #if LITTLEENDIAN
        return *(UInt16*)(this.CurrentPointer + offset);
  #elif BIGENDIAN
        ushort ush = *(ushort*)(this.CurrentPointer + offset);
        return (UInt16)((ush << 8) | (ush >> 8));
  #endif
      }
  
      internal UInt32 PeekUInt32(
        int offset
      ) {
  #if COMPACTFX
        if ((int)(this.CurrentPointer + offset) % 4 != 0) return UnalignedPeekUInt32(offset);
  #endif
  #if LITTLEENDIAN
        return *(UInt32*)(this.CurrentPointer + offset);
  #elif BIGENDIAN
        uint uin = *(uint*)(this.CurrentPointer + offset);
        uin = (uin >> 16) | (uin << 16);
        uin = ((uin & 0xFF00FF00) >> 8) | ((uin & 0x00FF00FF) << 8);
        return uin;
  #endif
      }
  
      internal UInt32 PeekUInt32(
        uint offset
      ) {
  #if COMPACTFX
        if ((int)(this.CurrentPointer + offset) % 4 != 0) return UnalignedPeekUInt32(offset);
  #endif
  #if LITTLEENDIAN
        return *(UInt32*)(this.CurrentPointer + offset);
  #elif BIGENDIAN
        uint uin = *(uint*)(this.CurrentPointer + offset);
        uin = (uin >> 16) | (uin << 16);
        uin = ((uin & 0xFF00FF00) >> 8) | ((uin & 0x00FF00FF) << 8);
        return uin;
  #endif
      }
  
  #if COMPACTFX
      private Int16 UnalignedPeekInt16(
        int offset
      ) {
        byte b1 = *(this.CurrentPointer + offset);
        byte b2 = *(this.CurrentPointer + offset + 1);
  #if LITTLEENDIAN
        return (Int16)((b2 << 8) | b1);
  #elif BIGENDIAN
        return (Int16)((b1 << 8) | b2);
  #endif
      }
  
      private Int32 UnalignedPeekInt32(
        int offset
      ) {
        byte b1 = *(this.CurrentPointer + offset);
        byte b2 = *(this.CurrentPointer + offset + 1);
        byte b3 = *(this.CurrentPointer + offset + 2);
        byte b4 = *(this.CurrentPointer + offset + 3);
  #if LITTLEENDIAN
        return (Int32)((b4 << 24) | (b3 << 16) | (b2 << 8) | b1);
  #elif BIGENDIAN
        return (Int32)((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);
  #endif
      }
  
      private UInt16 UnalignedPeekUInt16(
        int offset
      ) {
        byte b1 = *(this.CurrentPointer + offset);
        byte b2 = *(this.CurrentPointer + offset + 1);
  #if LITTLEENDIAN
        return (UInt16)((b2 << 8) | b1);
  #elif BIGENDIAN
        return (UInt16)((b1 << 8) | b2);
  #endif
      }
  
      private UInt16 UnalignedPeekUInt16(
        uint offset
      ) {
        byte b1 = *(this.CurrentPointer + offset);
        byte b2 = *(this.CurrentPointer + offset + 1);
  #if LITTLEENDIAN
        return (UInt16)((b2 << 8) | b1);
  #elif BIGENDIAN
        return (UInt16)((b1 << 8) | b2);
  #endif
      }
  
      private UInt32 UnalignedPeekUInt32(
        int offset
      ) {
        byte b1 = *(this.CurrentPointer + offset);
        byte b2 = *(this.CurrentPointer + offset + 1);
        byte b3 = *(this.CurrentPointer + offset + 2);
        byte b4 = *(this.CurrentPointer + offset + 3);
  #if LITTLEENDIAN
        return (UInt32)((b4 << 24) | (b3 << 16) | (b2 << 8) | b1);
  #elif BIGENDIAN
        return (UInt32)((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);
  #endif
      }
  
      private UInt32 UnalignedPeekUInt32(
        uint offset
      ) {
        byte b1 = *(this.CurrentPointer + offset);
        byte b2 = *(this.CurrentPointer + offset + 1);
        byte b3 = *(this.CurrentPointer + offset + 2);
        byte b4 = *(this.CurrentPointer + offset + 3);
  #if LITTLEENDIAN
        return (UInt32)((b4 << 24) | (b3 << 16) | (b2 << 8) | b1);
  #elif BIGENDIAN
        return (UInt32)((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);
  #endif
      }
  #endif
  
      internal UInt32 PeekReference(
        int offset,
        bool smallRefSize
      ) {
        if (smallRefSize)
          return this.PeekUInt16(offset);
        return this.PeekUInt32(offset);
      }
  
      internal UInt32 PeekReference(
        uint offset,
        bool smallRefSize
      ) {
        if (smallRefSize)
          return this.PeekUInt16(offset);
        return this.PeekUInt32(offset);
      }
  
      internal Guid PeekGuid(
        int offset
      ) {
  #if LITTLEENDIAN && !COMPACTFX
        return *(Guid*)(this.CurrentPointer + offset);
  #else
        int int1 = this.PeekInt32(0);
        short short1 = this.PeekInt16(sizeof(int));
        short short2 = this.PeekInt16(sizeof(int) + sizeof(short));
        byte[] bytes = this.PeekBytes(sizeof(int) + 2 * sizeof(short), 8);
        return new Guid(int1, short1, short2, bytes);
  #endif
      }
  
      internal byte[] PeekBytes(
        int offset,
        int byteCount
      ) {
        byte[] result = new byte[byteCount];
        byte* pIter = this.CurrentPointer + offset;
        byte* pEnd = pIter + byteCount;
        fixed (byte* pResult = result) {
          byte* resultIter = pResult;
          while (pIter < pEnd) {
            *resultIter = *pIter;
            pIter++;
            resultIter++;
          }
        }
        return result;
      }
  
      private static string ScanUTF16WithSize(byte* bytePtr, int byteCount) {
  #if COMPACTFX
        if ((int)bytePtr % 2 != 0) return UnalignedScanUTF16WithSize(bytePtr, byteCount);
  #endif
        int charsToRead = byteCount / sizeof(Char);
        char* pc = (char*)bytePtr;
        char[] buffer = new char[charsToRead];
        fixed (char* uBuffer = buffer) {
          char* iterBuffer = uBuffer;
          char* endBuffer = uBuffer + charsToRead;
          while (iterBuffer < endBuffer) {
  #if LITTLEENDIAN
            *iterBuffer++ = *pc++;
  #else
            ushort ush = (ushort)*pc++;
            *iterBuffer++ = (char)((ush >> 8) | (ush << 8));
  #endif
          }
        }
        return new String(buffer, 0, charsToRead);
      }
  
  #if COMPACTFX
      private static string UnalignedScanUTF16WithSize(byte* bytePtr, int byteCount) {
        int charsToRead = byteCount / sizeof(Char);
        char[] buffer = new char[charsToRead];
        fixed (char* uBuffer = buffer) {
          char* iterBuffer = uBuffer;
          char* endBuffer = uBuffer + charsToRead;
          while (iterBuffer < endBuffer) {
            byte b1 = *bytePtr++;
            byte b2 = *bytePtr++;
  #if LITTLEENDIAN
            *iterBuffer++ = (char)((b2 << 8) | b1);
  #else
            *iterBuffer++ = (char)((b1 << 8) | b2);
  #endif
          }
        }
        return new String(buffer, 0, charsToRead);
      }
  #endif
  
      internal string PeekUTF16WithSize(
        int offset,
        int byteCount
      ) {
        return MemoryReader.ScanUTF16WithSize(this.CurrentPointer + offset, byteCount);
      }
  
      internal int PeekCompressedInt32(
        int offset,
        out int numberOfBytesRead
      ) {
  #if LITTLEENDIAN
        byte headerByte = this.PeekByte(offset);
        int result;
        if ((headerByte & 0x80) == 0x00) {
          result = headerByte;
          numberOfBytesRead = 1;
        } else if ((headerByte & 0x40) == 0x00) {
          result = ((headerByte & 0x3f) << 8) | this.PeekByte(offset + 1);
          numberOfBytesRead = 2;
        } else if (headerByte == 0xFF) {
          result = -1;
          numberOfBytesRead = 1;
        } else {
          int offsetIter = offset + 1;
          result = ((headerByte & 0x3f) << 24) | (this.PeekByte(offsetIter) << 16);
          offsetIter++;
          result |= (this.PeekByte(offsetIter) << 8);
          offsetIter++;
          result |= this.PeekByte(offsetIter);
          numberOfBytesRead = 4;
        }
        return result;
  #elif BIGENDIAN
        byte headerByte = this.PeekByte(offset);
        int result;
        if ((headerByte & 0x80) == 0x00) {
          result = headerByte;
          numberOfBytesRead = 1;
        } else if ((headerByte & 0x40) == 0x00) {
  
gt:         result = (headerByte & 0x3f) | (this.PeekByte(offset + 1) << 8);