do not check order sequence if option /order was not used
[mono.git] / mcs / class / IKVM.Reflection / Reader / ByteReader.cs
1 /*
2   Copyright (C) 2009 Jeroen Frijters
3
4   This software is provided 'as-is', without any express or implied
5   warranty.  In no event will the authors be held liable for any damages
6   arising from the use of this software.
7
8   Permission is granted to anyone to use this software for any purpose,
9   including commercial applications, and to alter it and redistribute it
10   freely, subject to the following restrictions:
11
12   1. The origin of this software must not be misrepresented; you must not
13      claim that you wrote the original software. If you use this software
14      in a product, an acknowledgment in the product documentation would be
15      appreciated but is not required.
16   2. Altered source versions must be plainly marked as such, and must not be
17      misrepresented as being the original software.
18   3. This notice may not be removed or altered from any source distribution.
19
20   Jeroen Frijters
21   jeroen@frijters.net
22   
23 */
24 using System;
25 using System.Collections.Generic;
26 using System.Text;
27
28 namespace IKVM.Reflection.Reader
29 {
30         sealed class ByteReader
31         {
32                 private byte[] buffer;
33                 private int pos;
34                 private int end;
35
36                 internal ByteReader(byte[] buffer, int offset, int length)
37                 {
38                         this.buffer = buffer;
39                         this.pos = offset;
40                         this.end = pos + length;
41                 }
42
43                 internal static ByteReader FromBlob(byte[] blobHeap, int blob)
44                 {
45                         ByteReader br = new ByteReader(blobHeap, blob, 4);
46                         int length = br.ReadCompressedInt();
47                         br.end = br.pos + length;
48                         return br;
49                 }
50
51                 internal int Length
52                 {
53                         get { return end - pos; }
54                 }
55
56                 internal byte PeekByte()
57                 {
58                         if (pos == end)
59                                 throw new BadImageFormatException();
60                         return buffer[pos];
61                 }
62
63                 internal byte ReadByte()
64                 {
65                         if (pos == end)
66                                 throw new BadImageFormatException();
67                         return buffer[pos++];
68                 }
69
70                 internal byte[] ReadBytes(int count)
71                 {
72                         if (count < 0)
73                                 throw new BadImageFormatException();
74                         if (end - pos < count)
75                                 throw new BadImageFormatException();
76                         byte[] buf = new byte[count];
77                         Buffer.BlockCopy(buffer, pos, buf, 0, count);
78                         pos += count;
79                         return buf;
80                 }
81
82                 internal int ReadCompressedInt()
83                 {
84                         byte b1 = ReadByte();
85                         if (b1 <= 0x7F)
86                         {
87                                 return b1;
88                         }
89                         else if ((b1 & 0xC0) == 0x80)
90                         {
91                                 byte b2 = ReadByte();
92                                 return ((b1 & 0x3F) << 8) | b2;
93                         }
94                         else
95                         {
96                                 byte b2 = ReadByte();
97                                 byte b3 = ReadByte();
98                                 byte b4 = ReadByte();
99                                 return ((b1 & 0x3F) << 24) + (b2 << 16) + (b3 << 8) + b4;
100                         }
101                 }
102
103                 internal string ReadString()
104                 {
105                         if (PeekByte() == 0xFF)
106                         {
107                                 pos++;
108                                 return null;
109                         }
110                         int length = ReadCompressedInt();
111                         string str = Encoding.UTF8.GetString(buffer, pos, length);
112                         pos += length;
113                         return str;
114                 }
115
116                 internal char ReadChar()
117                 {
118                         return (char)ReadInt16();
119                 }
120
121                 internal sbyte ReadSByte()
122                 {
123                         return (sbyte)ReadByte();
124                 }
125
126                 internal short ReadInt16()
127                 {
128                         if (end - pos < 2)
129                                 throw new BadImageFormatException();
130                         byte b1 = buffer[pos++];
131                         byte b2 = buffer[pos++];
132                         return (short)(b1 | (b2 << 8));
133                 }
134
135                 internal ushort ReadUInt16()
136                 {
137                         return (ushort)ReadInt16();
138                 }
139
140                 internal int ReadInt32()
141                 {
142                         if (end - pos < 4)
143                                 throw new BadImageFormatException();
144                         byte b1 = buffer[pos++];
145                         byte b2 = buffer[pos++];
146                         byte b3 = buffer[pos++];
147                         byte b4 = buffer[pos++];
148                         return (int)(b1 | (b2 << 8) | (b3 << 16) | (b4 << 24));
149                 }
150
151                 internal uint ReadUInt32()
152                 {
153                         return (uint)ReadInt32();
154                 }
155
156                 internal long ReadInt64()
157                 {
158                         ulong lo = ReadUInt32();
159                         ulong hi = ReadUInt32();
160                         return (long)(lo | (hi << 32));
161                 }
162
163                 internal ulong ReadUInt64()
164                 {
165                         return (ulong)ReadInt64();
166                 }
167
168                 internal float ReadSingle()
169                 {
170                         return SingleConverter.Int32BitsToSingle(ReadInt32());
171                 }
172
173                 internal double ReadDouble()
174                 {
175                         return BitConverter.Int64BitsToDouble(ReadInt64());
176                 }
177
178                 internal ByteReader Slice(int length)
179                 {
180                         if (end - pos < length)
181                                 throw new BadImageFormatException();
182                         ByteReader br = new ByteReader(buffer, pos, length);
183                         pos += length;
184                         return br;
185                 }
186
187                 // NOTE this method only works if the original offset was aligned and for alignments that are a power of 2
188                 internal void Align(int alignment)
189                 {
190                         alignment--;
191                         pos = (pos + alignment) & ~alignment;
192                 }
193         }
194 }