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 private void Grow(int minGrow)
67 byte[] newbuf = new byte[Math.Max(buffer.Length + minGrow, buffer.Length * 2)];
68 Buffer.BlockCopy(buffer, 0, newbuf, 0, buffer.Length);
72 // NOTE this does not advance the position
73 internal int GetInt32AtCurrentPosition()
76 + (buffer[pos + 1] << 8)
77 + (buffer[pos + 2] << 16)
78 + (buffer[pos + 3] << 24);
81 // NOTE this does not advance the position
82 internal byte GetByteAtCurrentPosition()
87 internal void Write(byte[] value)
89 if (pos + value.Length > buffer.Length)
91 Buffer.BlockCopy(value, 0, buffer, pos, value.Length);
95 internal void Write(byte value)
97 if (pos == buffer.Length)
99 buffer[pos++] = value;
102 internal void Write(sbyte value)
107 internal void Write(ushort value)
112 internal void Write(short value)
114 if (pos + 2 > buffer.Length)
116 buffer[pos++] = (byte)value;
117 buffer[pos++] = (byte)(value >> 8);
120 internal void Write(uint value)
125 internal void Write(int value)
127 if (pos + 4 > buffer.Length)
129 buffer[pos++] = (byte)value;
130 buffer[pos++] = (byte)(value >> 8);
131 buffer[pos++] = (byte)(value >> 16);
132 buffer[pos++] = (byte)(value >> 24);
135 internal void Write(ulong value)
140 internal void Write(long value)
142 if (pos + 8 > buffer.Length)
144 buffer[pos++] = (byte)value;
145 buffer[pos++] = (byte)(value >> 8);
146 buffer[pos++] = (byte)(value >> 16);
147 buffer[pos++] = (byte)(value >> 24);
148 buffer[pos++] = (byte)(value >> 32);
149 buffer[pos++] = (byte)(value >> 40);
150 buffer[pos++] = (byte)(value >> 48);
151 buffer[pos++] = (byte)(value >> 56);
154 internal void Write(float value)
156 Write(SingleConverter.SingleToInt32Bits(value));
159 internal void Write(double value)
161 Write(BitConverter.DoubleToInt64Bits(value));
164 internal void Write(string str)
172 byte[] buf = Encoding.UTF8.GetBytes(str);
173 WriteCompressedInt(buf.Length);
178 internal void WriteCompressedInt(int value)
184 else if (value <= 0x3FFF)
186 Write((byte)(0x80 | (value >> 8)));
191 Write((byte)(0xC0 | (value >> 24)));
192 Write((byte)(value >> 16));
193 Write((byte)(value >> 8));
198 internal void Write(ByteBuffer bb)
200 if (pos + bb.Length > buffer.Length)
202 Buffer.BlockCopy(bb.buffer, 0, buffer, pos, bb.Length);
206 internal void WriteTo(System.IO.Stream stream)
208 stream.Write(buffer, 0, this.Length);
211 internal void Clear()
217 internal void Align(int alignment)
219 if (pos + alignment > buffer.Length)
221 int newpos = (pos + alignment - 1) & ~(alignment - 1);
226 internal void WriteTypeDefOrRefEncoded(int token)
230 case TypeDefTable.Index:
231 WriteCompressedInt((token & 0xFFFFFF) << 2 | 0);
233 case TypeRefTable.Index:
234 WriteCompressedInt((token & 0xFFFFFF) << 2 | 1);
236 case TypeSpecTable.Index:
237 WriteCompressedInt((token & 0xFFFFFF) << 2 | 2);
240 throw new InvalidOperationException();
244 internal void Write(System.IO.Stream stream)
246 const int chunkSize = 8192;
249 if (pos + chunkSize > buffer.Length)
251 int read = stream.Read(buffer, pos, chunkSize);
260 internal byte[] ToArray()
262 byte[] buf = new byte[pos];
263 Buffer.BlockCopy(buffer, 0, buf, 0, pos);
267 internal static ByteBuffer Wrap(byte[] buf)
269 return new ByteBuffer(buf, buf.Length);
272 internal static ByteBuffer Wrap(byte[] buf, int length)
274 return new ByteBuffer(buf, length);
277 internal bool Match(int pos, ByteBuffer bb2, int pos2, int len)
279 for (int i = 0; i < len; i++)
281 if (buffer[pos + i] != bb2.buffer[pos2 + i])
292 int len = this.Length;
293 for (int i = 0; i < len; i++)
301 internal IKVM.Reflection.Reader.ByteReader GetBlob(int offset)
303 return IKVM.Reflection.Reader.ByteReader.FromBlob(buffer, offset);