IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
ByteReader.cs
Go to the documentation of this file.
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*/
24using System;
25using System.Reflection.Metadata;
26using System.Reflection.Metadata.Ecma335;
27using System.Text;
28
30{
31
32 sealed class ByteReader
33 {
34
35 readonly byte[] buffer;
36 int pos;
37 int end;
38
45 internal ByteReader(byte[] buffer, int offset, int length)
46 {
47 this.buffer = buffer;
48 this.pos = offset;
49 this.end = pos + length;
50 }
51
52 internal static ByteReader FromBlob(byte[] blobHeap, BlobHandle blob)
53 {
54 var br = new ByteReader(blobHeap, MetadataTokens.GetHeapOffset(blob), 4);
55 var length = br.ReadCompressedUInt();
56 br.end = br.pos + length;
57 return br;
58 }
59
60 internal int Length
61 {
62 get { return end - pos; }
63 }
64
65 internal byte PeekByte()
66 {
67 if (pos == end)
68 throw new BadImageFormatException();
69
70 return buffer[pos];
71 }
72
73 internal byte ReadByte()
74 {
75 if (pos == end)
76 throw new BadImageFormatException();
77
78 return buffer[pos++];
79 }
80
81 internal byte[] ReadBytes(int count)
82 {
83 if (count < 0)
84 throw new BadImageFormatException();
85 if (end - pos < count)
86 throw new BadImageFormatException();
87
88 var buf = new byte[count];
89 Buffer.BlockCopy(buffer, pos, buf, 0, count);
90 pos += count;
91 return buf;
92 }
93
94 internal int ReadCompressedUInt()
95 {
96 var b1 = ReadByte();
97 if (b1 <= 0x7F)
98 {
99 return b1;
100 }
101 else if ((b1 & 0xC0) == 0x80)
102 {
103 var b2 = ReadByte();
104 return ((b1 & 0x3F) << 8) | b2;
105 }
106 else
107 {
108 var b2 = ReadByte();
109 var b3 = ReadByte();
110 var b4 = ReadByte();
111 return ((b1 & 0x3F) << 24) + (b2 << 16) + (b3 << 8) + b4;
112 }
113 }
114
115 internal int ReadCompressedInt()
116 {
117 var b1 = PeekByte();
118 var value = ReadCompressedUInt();
119 if ((value & 1) == 0)
120 {
121 return value >> 1;
122 }
123 else
124 {
125 return (b1 & 0xC0) switch
126 {
127 0 or 0x40 => (value >> 1) - 0x40,
128 0x80 => (value >> 1) - 0x2000,
129 _ => (value >> 1) - 0x10000000,
130 };
131 }
132 }
133
134 internal string ReadString()
135 {
136 if (PeekByte() == 0xFF)
137 {
138 pos++;
139 return null;
140 }
141
142 var length = ReadCompressedUInt();
143 var str = Encoding.UTF8.GetString(buffer, pos, length);
144 pos += length;
145 return str;
146 }
147
148 internal char ReadChar()
149 {
150 return (char)ReadInt16();
151 }
152
153 internal sbyte ReadSByte()
154 {
155 return (sbyte)ReadByte();
156 }
157
158 internal short ReadInt16()
159 {
160 if (end - pos < 2)
161 throw new BadImageFormatException();
162
163 var b1 = buffer[pos++];
164 var b2 = buffer[pos++];
165 return (short)(b1 | (b2 << 8));
166 }
167
168 internal ushort ReadUInt16()
169 {
170 return (ushort)ReadInt16();
171 }
172
173 internal int ReadInt32()
174 {
175 if (end - pos < 4)
176 throw new BadImageFormatException();
177
178 var b1 = buffer[pos++];
179 var b2 = buffer[pos++];
180 var b3 = buffer[pos++];
181 var b4 = buffer[pos++];
182 return (int)(b1 | (b2 << 8) | (b3 << 16) | (b4 << 24));
183 }
184
185 internal uint ReadUInt32()
186 {
187 return (uint)ReadInt32();
188 }
189
190 internal long ReadInt64()
191 {
192 ulong lo = ReadUInt32();
193 ulong hi = ReadUInt32();
194 return (long)(lo | (hi << 32));
195 }
196
197 internal ulong ReadUInt64()
198 {
199 return (ulong)ReadInt64();
200 }
201
202 internal float ReadSingle()
203 {
204 return SingleConverter.Int32BitsToSingle(ReadInt32());
205 }
206
207 internal double ReadDouble()
208 {
209 return BitConverter.Int64BitsToDouble(ReadInt64());
210 }
211
212 internal ByteReader Slice(int length)
213 {
214 if (end - pos < length)
215 throw new BadImageFormatException();
216
217 var br = new ByteReader(buffer, pos, length);
218 pos += length;
219 return br;
220 }
221
222 // NOTE this method only works if the original offset was aligned and for alignments that are a power of 2
223 internal void Align(int alignment)
224 {
225 alignment--;
226 pos = (pos + alignment) & ~alignment;
227 }
228
229 }
230
231}