~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/ikvm/reflect/Writer/ByteBuffer.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
*/
 
24
using System;
 
25
using System.Collections.Generic;
 
26
using System.Text;
 
27
using IKVM.Reflection.Metadata;
 
28
 
 
29
namespace IKVM.Reflection.Writer
 
30
{
 
31
        sealed class ByteBuffer
 
32
        {
 
33
                private byte[] buffer;
 
34
                private int pos;
 
35
                private int __length;   // __length is only valid if > pos, otherwise pos is the current length
 
36
 
 
37
                internal ByteBuffer(int initialCapacity)
 
38
                {
 
39
                        buffer = new byte[initialCapacity];
 
40
                }
 
41
 
 
42
                private ByteBuffer(byte[] wrap, int length)
 
43
                {
 
44
                        this.buffer = wrap;
 
45
                        this.pos = length;
 
46
                }
 
47
 
 
48
                internal int Position
 
49
                {
 
50
                        get { return pos; }
 
51
                        set
 
52
                        {
 
53
                                if (value > this.Length || value > buffer.Length)
 
54
                                        throw new ArgumentOutOfRangeException();
 
55
                                __length = Math.Max(__length, pos);
 
56
                                pos = value;
 
57
                        }
 
58
                }
 
59
 
 
60
                internal int Length
 
61
                {
 
62
                        get { return Math.Max(pos, __length); }
 
63
                }
 
64
 
 
65
                // insert count bytes at the current position (without advancing the current position)
 
66
                internal void Insert(int count)
 
67
                {
 
68
                        if (count > 0)
 
69
                        {
 
70
                                int len = this.Length;
 
71
                                int free = buffer.Length - len;
 
72
                                if (free < count)
 
73
                                {
 
74
                                        Grow(count - free);
 
75
                                }
 
76
                                Buffer.BlockCopy(buffer, pos, buffer, pos + count, len - pos);
 
77
                                __length = Math.Max(__length, pos) + count;
 
78
                        }
 
79
                        else if (count < 0)
 
80
                        {
 
81
                                throw new ArgumentOutOfRangeException("count");
 
82
                        }
 
83
                }
 
84
 
 
85
                private void Grow(int minGrow)
 
86
                {
 
87
                        byte[] newbuf = new byte[Math.Max(buffer.Length + minGrow, buffer.Length * 2)];
 
88
                        Buffer.BlockCopy(buffer, 0, newbuf, 0, buffer.Length);
 
89
                        buffer = newbuf;
 
90
                }
 
91
 
 
92
                // NOTE this does not advance the position
 
93
                internal int GetInt32AtCurrentPosition()
 
94
                {
 
95
                        return buffer[pos]
 
96
                                + (buffer[pos + 1] << 8)
 
97
                                + (buffer[pos + 2] << 16)
 
98
                                + (buffer[pos + 3] << 24);
 
99
                }
 
100
 
 
101
                // NOTE this does not advance the position
 
102
                internal byte GetByteAtCurrentPosition()
 
103
                {
 
104
                        return buffer[pos];
 
105
                }
 
106
 
 
107
                // return the number of bytes that the compressed int at the current position takes
 
108
                internal int GetCompressedUIntLength()
 
109
                {
 
110
                        switch (buffer[pos] & 0xC0)
 
111
                        {
 
112
                                default:
 
113
                                        return 1;
 
114
                                case 0x80:
 
115
                                        return 2;
 
116
                                case 0xC0:
 
117
                                        return 4;
 
118
                        }
 
119
                }
 
120
 
 
121
                internal void Write(byte[] value)
 
122
                {
 
123
                        if (pos + value.Length > buffer.Length)
 
124
                                Grow(value.Length);
 
125
                        Buffer.BlockCopy(value, 0, buffer, pos, value.Length);
 
126
                        pos += value.Length;
 
127
                }
 
128
 
 
129
                internal void Write(byte value)
 
130
                {
 
131
                        if (pos == buffer.Length)
 
132
                                Grow(1);
 
133
                        buffer[pos++] = value;
 
134
                }
 
135
 
 
136
                internal void Write(sbyte value)
 
137
                {
 
138
                        Write((byte)value);
 
139
                }
 
140
 
 
141
                internal void Write(ushort value)
 
142
                {
 
143
                        Write((short)value);
 
144
                }
 
145
 
 
146
                internal void Write(short value)
 
147
                {
 
148
                        if (pos + 2 > buffer.Length)
 
149
                                Grow(2);
 
150
                        buffer[pos++] = (byte)value;
 
151
                        buffer[pos++] = (byte)(value >> 8);
 
152
                }
 
153
 
 
154
                internal void Write(uint value)
 
155
                {
 
156
                        Write((int)value);
 
157
                }
 
158
        
 
159
                internal void Write(int value)
 
160
                {
 
161
                        if (pos + 4 > buffer.Length)
 
162
                                Grow(4);
 
163
                        buffer[pos++] = (byte)value;
 
164
                        buffer[pos++] = (byte)(value >> 8);
 
165
                        buffer[pos++] = (byte)(value >> 16);
 
166
                        buffer[pos++] = (byte)(value >> 24);
 
167
                }
 
168
 
 
169
                internal void Write(ulong value)
 
170
                {
 
171
                        Write((long)value);
 
172
                }
 
173
 
 
174
                internal void Write(long value)
 
175
                {
 
176
                        if (pos + 8 > buffer.Length)
 
177
                                Grow(8);
 
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);
 
186
                }
 
187
 
 
188
                internal void Write(float value)
 
189
                {
 
190
                        Write(SingleConverter.SingleToInt32Bits(value));
 
191
                }
 
192
 
 
193
                internal void Write(double value)
 
194
                {
 
195
                        Write(BitConverter.DoubleToInt64Bits(value));
 
196
                }
 
197
 
 
198
                internal void Write(string str)
 
199
                {
 
200
                        if (str == null)
 
201
                        {
 
202
                                Write((byte)0xFF);
 
203
                        }
 
204
                        else
 
205
                        {
 
206
                                byte[] buf = Encoding.UTF8.GetBytes(str);
 
207
                                WriteCompressedUInt(buf.Length);
 
208
                                Write(buf);
 
209
                        }
 
210
                }
 
211
 
 
212
                internal void WriteCompressedUInt(int value)
 
213
                {
 
214
                        if (value <= 0x7F)
 
215
                        {
 
216
                                Write((byte)value);
 
217
                        }
 
218
                        else if (value <= 0x3FFF)
 
219
                        {
 
220
                                Write((byte)(0x80 | (value >> 8)));
 
221
                                Write((byte)value);
 
222
                        }
 
223
                        else
 
224
                        {
 
225
                                Write((byte)(0xC0 | (value >> 24)));
 
226
                                Write((byte)(value >> 16));
 
227
                                Write((byte)(value >> 8));
 
228
                                Write((byte)value);
 
229
                        }
 
230
                }
 
231
 
 
232
                internal void WriteCompressedInt(int value)
 
233
                {
 
234
                        if (value >= 0)
 
235
                        {
 
236
                                WriteCompressedUInt(value << 1);
 
237
                        }
 
238
                        else if (value >= -64)
 
239
                        {
 
240
                                value = ((value << 1) & 0x7F) | 1;
 
241
                                Write((byte)value);
 
242
                        }
 
243
                        else if (value >= -8192)
 
244
                        {
 
245
                                value = ((value << 1) & 0x3FFF) | 1;
 
246
                                Write((byte)(0x80 | (value >> 8)));
 
247
                                Write((byte)value);
 
248
                        }
 
249
                        else
 
250
                        {
 
251
                                value = ((value << 1) & 0x1FFFFFFF) | 1;
 
252
                                Write((byte)(0xC0 | (value >> 24)));
 
253
                                Write((byte)(value >> 16));
 
254
                                Write((byte)(value >> 8));
 
255
                                Write((byte)value);
 
256
                        }
 
257
                }
 
258
 
 
259
                internal void Write(ByteBuffer bb)
 
260
                {
 
261
                        if (pos + bb.Length > buffer.Length)
 
262
                                Grow(bb.Length);
 
263
                        Buffer.BlockCopy(bb.buffer, 0, buffer, pos, bb.Length);
 
264
                        pos += bb.Length;
 
265
                }
 
266
 
 
267
                internal void WriteTo(System.IO.Stream stream)
 
268
                {
 
269
                        stream.Write(buffer, 0, this.Length);
 
270
                }
 
271
 
 
272
                internal void Clear()
 
273
                {
 
274
                        pos = 0;
 
275
                        __length = 0;
 
276
                }
 
277
 
 
278
                internal void Align(int alignment)
 
279
                {
 
280
                        if (pos + alignment > buffer.Length)
 
281
                                Grow(alignment);
 
282
                        int newpos = (pos + alignment - 1) & ~(alignment - 1);
 
283
                        while (pos < newpos)
 
284
                                buffer[pos++] = 0;
 
285
                }
 
286
 
 
287
                internal void WriteTypeDefOrRefEncoded(int token)
 
288
                {
 
289
                        switch (token >> 24)
 
290
                        {
 
291
                                case TypeDefTable.Index:
 
292
                                        WriteCompressedUInt((token & 0xFFFFFF) << 2 | 0);
 
293
                                        break;
 
294
                                case TypeRefTable.Index:
 
295
                                        WriteCompressedUInt((token & 0xFFFFFF) << 2 | 1);
 
296
                                        break;
 
297
                                case TypeSpecTable.Index:
 
298
                                        WriteCompressedUInt((token & 0xFFFFFF) << 2 | 2);
 
299
                                        break;
 
300
                                default:
 
301
                                        throw new InvalidOperationException();
 
302
                        }
 
303
                }
 
304
 
 
305
                internal void Write(System.IO.Stream stream)
 
306
                {
 
307
                        const int chunkSize = 8192;
 
308
                        for (; ; )
 
309
                        {
 
310
                                if (pos + chunkSize > buffer.Length)
 
311
                                        Grow(chunkSize);
 
312
                                int read = stream.Read(buffer, pos, chunkSize);
 
313
                                if (read <= 0)
 
314
                                {
 
315
                                        break;
 
316
                                }
 
317
                                pos += read;
 
318
                        }
 
319
                }
 
320
 
 
321
                internal byte[] ToArray()
 
322
                {
 
323
                        int len = this.Length;
 
324
                        byte[] buf = new byte[len];
 
325
                        Buffer.BlockCopy(buffer, 0, buf, 0, len);
 
326
                        return buf;
 
327
                }
 
328
 
 
329
                internal static ByteBuffer Wrap(byte[] buf)
 
330
                {
 
331
                        return new ByteBuffer(buf, buf.Length);
 
332
                }
 
333
 
 
334
                internal static ByteBuffer Wrap(byte[] buf, int length)
 
335
                {
 
336
                        return new ByteBuffer(buf, length);
 
337
                }
 
338
 
 
339
                internal bool Match(int pos, ByteBuffer bb2, int pos2, int len)
 
340
                {
 
341
                        for (int i = 0; i < len; i++)
 
342
                        {
 
343
                                if (buffer[pos + i] != bb2.buffer[pos2 + i])
 
344
                                {
 
345
                                        return false;
 
346
                                }
 
347
                        }
 
348
                        return true;
 
349
                }
 
350
 
 
351
                internal int Hash()
 
352
                {
 
353
                        int hash = 0;
 
354
                        int len = this.Length;
 
355
                        for (int i = 0; i < len; i++)
 
356
                        {
 
357
                                hash *= 37;
 
358
                                hash ^= buffer[i];
 
359
                        }
 
360
                        return hash;
 
361
                }
 
362
 
 
363
                internal IKVM.Reflection.Reader.ByteReader GetBlob(int offset)
 
364
                {
 
365
                        return IKVM.Reflection.Reader.ByteReader.FromBlob(buffer, offset);
 
366
                }
 
367
        }
 
368
}