diff options
author | Jeroen Frijters <jeroen@frijters.net> | 2013-02-25 14:27:25 +0400 |
---|---|---|
committer | Jeroen Frijters <jeroen@frijters.net> | 2013-02-25 14:27:25 +0400 |
commit | 9b7577d079431bc017de44cb6b58949de1c52282 (patch) | |
tree | 542195f11cf00a5d98c58f1039a4782e8b9bdcd2 /ByteReader.cs |
Initial commit.
Diffstat (limited to 'ByteReader.cs')
-rw-r--r-- | ByteReader.cs | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/ByteReader.cs b/ByteReader.cs new file mode 100644 index 0000000..7e3c6f5 --- /dev/null +++ b/ByteReader.cs @@ -0,0 +1,194 @@ +/* + Copyright (C) 2009 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.Collections.Generic; +using System.Text; + +namespace IKVM.Reflection.Reader +{ + sealed class ByteReader + { + private byte[] buffer; + private int pos; + private int end; + + internal ByteReader(byte[] buffer, int offset, int length) + { + this.buffer = buffer; + this.pos = offset; + this.end = pos + length; + } + + internal static ByteReader FromBlob(byte[] blobHeap, int blob) + { + ByteReader br = new ByteReader(blobHeap, blob, 4); + int length = br.ReadCompressedInt(); + br.end = br.pos + length; + return br; + } + + internal int Length + { + get { return end - pos; } + } + + internal byte PeekByte() + { + if (pos == end) + throw new BadImageFormatException(); + return buffer[pos]; + } + + internal byte ReadByte() + { + if (pos == end) + throw new BadImageFormatException(); + return buffer[pos++]; + } + + internal byte[] ReadBytes(int count) + { + if (count < 0) + throw new BadImageFormatException(); + if (end - pos < count) + throw new BadImageFormatException(); + byte[] buf = new byte[count]; + Buffer.BlockCopy(buffer, pos, buf, 0, count); + pos += count; + return buf; + } + + internal int ReadCompressedInt() + { + byte b1 = ReadByte(); + if (b1 <= 0x7F) + { + return b1; + } + else if ((b1 & 0xC0) == 0x80) + { + byte b2 = ReadByte(); + return ((b1 & 0x3F) << 8) | b2; + } + else + { + byte b2 = ReadByte(); + byte b3 = ReadByte(); + byte b4 = ReadByte(); + return ((b1 & 0x3F) << 24) + (b2 << 16) + (b3 << 8) + b4; + } + } + + internal string ReadString() + { + if (PeekByte() == 0xFF) + { + pos++; + return null; + } + int length = ReadCompressedInt(); + string str = Encoding.UTF8.GetString(buffer, pos, length); + pos += length; + return str; + } + + internal char ReadChar() + { + return (char)ReadInt16(); + } + + internal sbyte ReadSByte() + { + return (sbyte)ReadByte(); + } + + internal short ReadInt16() + { + if (end - pos < 2) + throw new BadImageFormatException(); + byte b1 = buffer[pos++]; + byte b2 = buffer[pos++]; + return (short)(b1 | (b2 << 8)); + } + + internal ushort ReadUInt16() + { + return (ushort)ReadInt16(); + } + + internal int ReadInt32() + { + if (end - pos < 4) + throw new BadImageFormatException(); + byte b1 = buffer[pos++]; + byte b2 = buffer[pos++]; + byte b3 = buffer[pos++]; + byte b4 = buffer[pos++]; + return (int)(b1 | (b2 << 8) | (b3 << 16) | (b4 << 24)); + } + + internal uint ReadUInt32() + { + return (uint)ReadInt32(); + } + + internal long ReadInt64() + { + ulong lo = ReadUInt32(); + ulong hi = ReadUInt32(); + return (long)(lo | (hi << 32)); + } + + internal ulong ReadUInt64() + { + return (ulong)ReadInt64(); + } + + internal float ReadSingle() + { + return SingleConverter.Int32BitsToSingle(ReadInt32()); + } + + internal double ReadDouble() + { + return BitConverter.Int64BitsToDouble(ReadInt64()); + } + + internal ByteReader Slice(int length) + { + if (end - pos < length) + throw new BadImageFormatException(); + ByteReader br = new ByteReader(buffer, pos, length); + pos += length; + return br; + } + + // NOTE this method only works if the original offset was aligned and for alignments that are a power of 2 + internal void Align(int alignment) + { + alignment--; + pos = (pos + alignment) & ~alignment; + } + } +} |