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 GetCompressedIntLength()
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 WriteCompressedInt(buf.Length);
212 internal void WriteCompressedInt(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 Write(ByteBuffer bb)
234 if (pos + bb.Length > buffer.Length)
236 Buffer.BlockCopy(bb.buffer, 0, buffer, pos, bb.Length);
240 internal void WriteTo(System.IO.Stream stream)
242 stream.Write(buffer, 0, this.Length);
245 internal void Clear()
251 internal void Align(int alignment)
253 if (pos + alignment > buffer.Length)
255 int newpos = (pos + alignment - 1) & ~(alignment - 1);
260 internal void WriteTypeDefOrRefEncoded(int token)
264 case TypeDefTable.Index:
265 WriteCompressedInt((token & 0xFFFFFF) << 2 | 0);
267 case TypeRefTable.Index:
268 WriteCompressedInt((token & 0xFFFFFF) << 2 | 1);
270 case TypeSpecTable.Index:
271 WriteCompressedInt((token & 0xFFFFFF) << 2 | 2);
274 throw new InvalidOperationException();
278 internal void Write(System.IO.Stream stream)
280 const int chunkSize = 8192;
283 if (pos + chunkSize > buffer.Length)
285 int read = stream.Read(buffer, pos, chunkSize);
294 internal byte[] ToArray()
296 int len = this.Length;
297 byte[] buf = new byte[len];
298 Buffer.BlockCopy(buffer, 0, buf, 0, len);
302 internal static ByteBuffer Wrap(byte[] buf)
304 return new ByteBuffer(buf, buf.Length);
307 internal static ByteBuffer Wrap(byte[] buf, int length)
309 return new ByteBuffer(buf, length);
312 internal bool Match(int pos, ByteBuffer bb2, int pos2, int len)
314 for (int i = 0; i < len; i++)
316 if (buffer[pos + i] != bb2.buffer[pos2 + i])
327 int len = this.Length;
328 for (int i = 0; i < len; i++)
336 internal IKVM.Reflection.Reader.ByteReader GetBlob(int offset)
338 return IKVM.Reflection.Reader.ByteReader.FromBlob(buffer, offset);