IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
ByteBuffer.cs
Go to the documentation of this file.
1/*
2 Copyright (C) 2008 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.Collections.Generic;
26using System.Reflection.Metadata;
27using System.Text;
28
30
32{
33
34 sealed class ByteBuffer
35 {
36
37 internal static ByteBuffer Wrap(byte[] buf)
38 {
39 return new ByteBuffer(buf, buf.Length);
40 }
41
42 internal static ByteBuffer Wrap(byte[] buf, int length)
43 {
44 return new ByteBuffer(buf, length);
45 }
46
47 byte[] buffer;
48 int pos;
49 int __length; // __length is only valid if > pos, otherwise pos is the current length
50
55 internal ByteBuffer(int initialCapacity)
56 {
57 buffer = new byte[initialCapacity];
58 }
59
65 private ByteBuffer(byte[] wrap, int length)
66 {
67 buffer = wrap;
68 pos = length;
69 }
70
71 internal int Position
72 {
73 get { return pos; }
74 set
75 {
76 if (value > Length || value > buffer.Length)
77 throw new ArgumentOutOfRangeException();
78
79 __length = Math.Max(__length, pos);
80 pos = value;
81 }
82 }
83
84 internal int Length
85 {
86 get { return Math.Max(pos, __length); }
87 }
88
94 internal void Insert(int count)
95 {
96 if (count > 0)
97 {
98 var len = Length;
99 var free = buffer.Length - len;
100 if (free < count)
101 Grow(count - free);
102
103 Buffer.BlockCopy(buffer, pos, buffer, pos + count, len - pos);
104 __length = Math.Max(__length, pos) + count;
105 }
106 else if (count < 0)
107 {
108 throw new ArgumentOutOfRangeException("count");
109 }
110 }
111
112 void Grow(int minGrow)
113 {
114 var newbuf = new byte[Math.Max(buffer.Length + minGrow, buffer.Length * 2)];
115 Buffer.BlockCopy(buffer, 0, newbuf, 0, buffer.Length);
116 buffer = newbuf;
117 }
118
126 internal int GetInt32AtCurrentPosition()
127 {
128 return buffer[pos]
129 + (buffer[pos + 1] << 8)
130 + (buffer[pos + 2] << 16)
131 + (buffer[pos + 3] << 24);
132 }
133
141 internal byte GetByteAtCurrentPosition()
142 {
143 return buffer[pos];
144 }
145
150 internal int GetCompressedUIntLength()
151 {
152 return (buffer[pos] & 0xC0) switch
153 {
154 0x80 => 2,
155 0xC0 => 4,
156 _ => 1,
157 };
158 }
159
160 internal void Write(byte[] value)
161 {
162 if (pos + value.Length > buffer.Length)
163 Grow(value.Length);
164
165 Buffer.BlockCopy(value, 0, buffer, pos, value.Length);
166 pos += value.Length;
167 }
168
169 internal void Write(byte value)
170 {
171 if (pos == buffer.Length)
172 Grow(1);
173 buffer[pos++] = value;
174 }
175
176 internal void Write(sbyte value)
177 {
178 Write((byte)value);
179 }
180
181 internal void Write(ushort value)
182 {
183 Write((short)value);
184 }
185
186 internal void Write(short value)
187 {
188 if (pos + 2 > buffer.Length)
189 Grow(2);
190
191 buffer[pos++] = (byte)value;
192 buffer[pos++] = (byte)(value >> 8);
193 }
194
195 internal void Write(uint value)
196 {
197 Write((int)value);
198 }
199
200 internal void Write(int value)
201 {
202 if (pos + 4 > buffer.Length)
203 Grow(4);
204
205 buffer[pos++] = (byte)value;
206 buffer[pos++] = (byte)(value >> 8);
207 buffer[pos++] = (byte)(value >> 16);
208 buffer[pos++] = (byte)(value >> 24);
209 }
210
211 internal void Write(ulong value)
212 {
213 Write((long)value);
214 }
215
216 internal void Write(long value)
217 {
218 if (pos + 8 > buffer.Length)
219 Grow(8);
220 buffer[pos++] = (byte)value;
221 buffer[pos++] = (byte)(value >> 8);
222 buffer[pos++] = (byte)(value >> 16);
223 buffer[pos++] = (byte)(value >> 24);
224 buffer[pos++] = (byte)(value >> 32);
225 buffer[pos++] = (byte)(value >> 40);
226 buffer[pos++] = (byte)(value >> 48);
227 buffer[pos++] = (byte)(value >> 56);
228 }
229
230 internal void Write(float value)
231 {
232 Write(SingleConverter.SingleToInt32Bits(value));
233 }
234
235 internal void Write(double value)
236 {
237 Write(BitConverter.DoubleToInt64Bits(value));
238 }
239
240 internal void Write(string str)
241 {
242 if (str == null)
243 {
244 Write((byte)0xFF);
245 }
246 else
247 {
248 var buf = Encoding.UTF8.GetBytes(str);
249 WriteCompressedUInt(buf.Length);
250 Write(buf);
251 }
252 }
253
254 internal void WriteCompressedUInt(int value)
255 {
256 if (value <= 0x7F)
257 {
258 Write((byte)value);
259 }
260 else if (value <= 0x3FFF)
261 {
262 Write((byte)(0x80 | (value >> 8)));
263 Write((byte)value);
264 }
265 else
266 {
267 Write((byte)(0xC0 | (value >> 24)));
268 Write((byte)(value >> 16));
269 Write((byte)(value >> 8));
270 Write((byte)value);
271 }
272 }
273
274 internal void WriteCompressedInt(int value)
275 {
276 if (value >= 0)
277 {
278 WriteCompressedUInt(value << 1);
279 }
280 else if (value >= -64)
281 {
282 value = ((value << 1) & 0x7F) | 1;
283 Write((byte)value);
284 }
285 else if (value >= -8192)
286 {
287 value = ((value << 1) & 0x3FFF) | 1;
288 Write((byte)(0x80 | (value >> 8)));
289 Write((byte)value);
290 }
291 else
292 {
293 value = ((value << 1) & 0x1FFFFFFF) | 1;
294 Write((byte)(0xC0 | (value >> 24)));
295 Write((byte)(value >> 16));
296 Write((byte)(value >> 8));
297 Write((byte)value);
298 }
299 }
300
301 internal void Write(ByteBuffer bb)
302 {
303 if (pos + bb.Length > buffer.Length)
304 Grow(bb.Length);
305
306 Buffer.BlockCopy(bb.buffer, 0, buffer, pos, bb.Length);
307 pos += bb.Length;
308 }
309
314 internal void Write(BlobBuilder blobBuilder)
315 {
316 Write(blobBuilder.GetBlobs());
317 }
318
323 internal void Write(IEnumerable<Blob> blobs)
324 {
325 foreach (var blob in blobs)
326 Write(blob.GetBytes());
327 }
328
333 internal void Write(ArraySegment<byte> bytes)
334 {
335 Write(bytes.AsSpan());
336 }
337
342 internal void Write(ReadOnlySpan<byte> span)
343 {
344 // grow the internal buffer
345 if (pos + span.Length > buffer.Length)
346 Grow(span.Length);
347
348 // copy the span to the newly allocated space
349 span.CopyTo(buffer.AsSpan().Slice(pos, span.Length));
350 pos += span.Length;
351 }
352
353 internal void WriteTo(System.IO.Stream stream)
354 {
355 stream.Write(buffer, 0, this.Length);
356 }
357
358 internal void Clear()
359 {
360 pos = 0;
361 __length = 0;
362 }
363
364 internal void Align(int alignment)
365 {
366 if (pos + alignment > buffer.Length)
367 Grow(alignment);
368 int newpos = (pos + alignment - 1) & ~(alignment - 1);
369 while (pos < newpos)
370 buffer[pos++] = 0;
371 }
372
373 internal void WriteTypeDefOrRefEncoded(int token)
374 {
375 switch (token >> 24)
376 {
377 case TypeDefTable.Index:
378 WriteCompressedUInt((token & 0xFFFFFF) << 2 | 0);
379 break;
380 case TypeRefTable.Index:
381 WriteCompressedUInt((token & 0xFFFFFF) << 2 | 1);
382 break;
383 case TypeSpecTable.Index:
384 WriteCompressedUInt((token & 0xFFFFFF) << 2 | 2);
385 break;
386 default:
387 throw new InvalidOperationException();
388 }
389 }
390
391 internal byte[] ToArray()
392 {
393 var len = Length;
394 var buf = new byte[len];
395 Buffer.BlockCopy(buffer, 0, buf, 0, len);
396 return buf;
397 }
398
399 internal bool Match(int pos, ByteBuffer bb2, int pos2, int len)
400 {
401 for (int i = 0; i < len; i++)
402 if (buffer[pos + i] != bb2.buffer[pos2 + i])
403 return false;
404
405 return true;
406 }
407
408 internal int Hash()
409 {
410 int hash = 0;
411 int len = Length;
412 for (int i = 0; i < len; i++)
413 {
414 hash *= 37;
415 hash ^= buffer[i];
416 }
417
418 return hash;
419 }
420
421 }
422
423}