2
Copyright (C) 2008 Jeroen Frijters
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.
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:
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.
25
using System.Collections.Generic;
27
using IKVM.Reflection.Metadata;
29
namespace IKVM.Reflection.Writer
31
sealed class ByteBuffer
33
private byte[] buffer;
35
private int __length; // __length is only valid if > pos, otherwise pos is the current length
37
internal ByteBuffer(int initialCapacity)
39
buffer = new byte[initialCapacity];
42
private ByteBuffer(byte[] wrap, int length)
53
if (value > this.Length || value > buffer.Length)
54
throw new ArgumentOutOfRangeException();
55
__length = Math.Max(__length, pos);
62
get { return Math.Max(pos, __length); }
65
// insert count bytes at the current position (without advancing the current position)
66
internal void Insert(int count)
70
int len = this.Length;
71
int free = buffer.Length - len;
76
Buffer.BlockCopy(buffer, pos, buffer, pos + count, len - pos);
77
__length = Math.Max(__length, pos) + count;
81
throw new ArgumentOutOfRangeException("count");
85
private void Grow(int minGrow)
87
byte[] newbuf = new byte[Math.Max(buffer.Length + minGrow, buffer.Length * 2)];
88
Buffer.BlockCopy(buffer, 0, newbuf, 0, buffer.Length);
92
// NOTE this does not advance the position
93
internal int GetInt32AtCurrentPosition()
96
+ (buffer[pos + 1] << 8)
97
+ (buffer[pos + 2] << 16)
98
+ (buffer[pos + 3] << 24);
101
// NOTE this does not advance the position
102
internal byte GetByteAtCurrentPosition()
107
// return the number of bytes that the compressed int at the current position takes
108
internal int GetCompressedUIntLength()
110
switch (buffer[pos] & 0xC0)
121
internal void Write(byte[] value)
123
if (pos + value.Length > buffer.Length)
125
Buffer.BlockCopy(value, 0, buffer, pos, value.Length);
129
internal void Write(byte value)
131
if (pos == buffer.Length)
133
buffer[pos++] = value;
136
internal void Write(sbyte value)
141
internal void Write(ushort value)
146
internal void Write(short value)
148
if (pos + 2 > buffer.Length)
150
buffer[pos++] = (byte)value;
151
buffer[pos++] = (byte)(value >> 8);
154
internal void Write(uint value)
159
internal void Write(int value)
161
if (pos + 4 > buffer.Length)
163
buffer[pos++] = (byte)value;
164
buffer[pos++] = (byte)(value >> 8);
165
buffer[pos++] = (byte)(value >> 16);
166
buffer[pos++] = (byte)(value >> 24);
169
internal void Write(ulong value)
174
internal void Write(long value)
176
if (pos + 8 > buffer.Length)
178
buffer[pos++] = (byte)value;
179
buffer[pos++] = (byte)(value >> 8);
180
buffer[pos++] = (byte)(value >> 16);
181
buffer[pos++] = (byte)(value >> 24);
182
buffer[pos++] = (byte)(value >> 32);
183
buffer[pos++] = (byte)(value >> 40);
184
buffer[pos++] = (byte)(value >> 48);
185
buffer[pos++] = (byte)(value >> 56);
188
internal void Write(float value)
190
Write(SingleConverter.SingleToInt32Bits(value));
193
internal void Write(double value)
195
Write(BitConverter.DoubleToInt64Bits(value));
198
internal void Write(string str)
206
byte[] buf = Encoding.UTF8.GetBytes(str);
207
WriteCompressedUInt(buf.Length);
212
internal void WriteCompressedUInt(int value)
218
else if (value <= 0x3FFF)
220
Write((byte)(0x80 | (value >> 8)));
225
Write((byte)(0xC0 | (value >> 24)));
226
Write((byte)(value >> 16));
227
Write((byte)(value >> 8));
232
internal void WriteCompressedInt(int value)
236
WriteCompressedUInt(value << 1);
238
else if (value >= -64)
240
value = ((value << 1) & 0x7F) | 1;
243
else if (value >= -8192)
245
value = ((value << 1) & 0x3FFF) | 1;
246
Write((byte)(0x80 | (value >> 8)));
251
value = ((value << 1) & 0x1FFFFFFF) | 1;
252
Write((byte)(0xC0 | (value >> 24)));
253
Write((byte)(value >> 16));
254
Write((byte)(value >> 8));
259
internal void Write(ByteBuffer bb)
261
if (pos + bb.Length > buffer.Length)
263
Buffer.BlockCopy(bb.buffer, 0, buffer, pos, bb.Length);
267
internal void WriteTo(System.IO.Stream stream)
269
stream.Write(buffer, 0, this.Length);
272
internal void Clear()
278
internal void Align(int alignment)
280
if (pos + alignment > buffer.Length)
282
int newpos = (pos + alignment - 1) & ~(alignment - 1);
287
internal void WriteTypeDefOrRefEncoded(int token)
291
case TypeDefTable.Index:
292
WriteCompressedUInt((token & 0xFFFFFF) << 2 | 0);
294
case TypeRefTable.Index:
295
WriteCompressedUInt((token & 0xFFFFFF) << 2 | 1);
297
case TypeSpecTable.Index:
298
WriteCompressedUInt((token & 0xFFFFFF) << 2 | 2);
301
throw new InvalidOperationException();
305
internal void Write(System.IO.Stream stream)
307
const int chunkSize = 8192;
310
if (pos + chunkSize > buffer.Length)
312
int read = stream.Read(buffer, pos, chunkSize);
321
internal byte[] ToArray()
323
int len = this.Length;
324
byte[] buf = new byte[len];
325
Buffer.BlockCopy(buffer, 0, buf, 0, len);
329
internal static ByteBuffer Wrap(byte[] buf)
331
return new ByteBuffer(buf, buf.Length);
334
internal static ByteBuffer Wrap(byte[] buf, int length)
336
return new ByteBuffer(buf, length);
339
internal bool Match(int pos, ByteBuffer bb2, int pos2, int len)
341
for (int i = 0; i < len; i++)
343
if (buffer[pos + i] != bb2.buffer[pos2 + i])
354
int len = this.Length;
355
for (int i = 0; i < len; i++)
363
internal IKVM.Reflection.Reader.ByteReader GetBlob(int offset)
365
return IKVM.Reflection.Reader.ByteReader.FromBlob(buffer, offset);