5
// Jb Evain (jbevain@gmail.com)
7
// Copyright (c) 2008 - 2010 Jb Evain
9
// Permission is hereby granted, free of charge, to any person obtaining
10
// a copy of this software and associated documentation files (the
11
// "Software"), to deal in the Software without restriction, including
12
// without limitation the rights to use, copy, modify, merge, publish,
13
// distribute, sublicense, and/or sell copies of the Software, and to
14
// permit persons to whom the Software is furnished to do so, subject to
15
// the following conditions:
17
// The above copyright notice and this permission notice shall be
18
// included in all copies or substantial portions of the Software.
20
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
namespace Mono.Cecil.PE {
35
internal byte [] buffer;
37
internal int position;
41
this.buffer = Empty<byte>.Array;
44
public ByteBuffer (int length)
46
this.buffer = new byte [length];
49
public ByteBuffer (byte [] buffer)
51
this.buffer = buffer ?? Empty<byte>.Array;
52
this.length = this.buffer.Length;
55
public void Reset (byte [] buffer)
57
this.buffer = buffer ?? Empty<byte>.Array;
58
this.length = this.buffer.Length;
61
public void Advance (int length)
66
public byte ReadByte ()
68
return buffer [position++];
71
public sbyte ReadSByte ()
73
return (sbyte) ReadByte ();
76
public byte [] ReadBytes (int length)
78
var bytes = new byte [length];
79
Buffer.BlockCopy (buffer, position, bytes, 0, length);
84
public ushort ReadUInt16 ()
86
ushort value = (ushort) (buffer [position]
87
| (buffer [position + 1] << 8));
92
public short ReadInt16 ()
94
return (short) ReadUInt16 ();
97
public uint ReadUInt32 ()
99
uint value = (uint) (buffer [position]
100
| (buffer [position + 1] << 8)
101
| (buffer [position + 2] << 16)
102
| (buffer [position + 3] << 24));
107
public int ReadInt32 ()
109
return (int) ReadUInt32 ();
112
public ulong ReadUInt64 ()
114
uint low = ReadUInt32 ();
115
uint high = ReadUInt32 ();
117
return (((ulong) high) << 32) | low;
120
public long ReadInt64 ()
122
return (long) ReadUInt64 ();
125
public uint ReadCompressedUInt32 ()
127
byte first = ReadByte ();
128
if ((first & 0x80) == 0)
131
if ((first & 0x40) == 0)
132
return ((uint) (first & ~0x80) << 8)
135
return ((uint) (first & ~0xc0) << 24)
136
| (uint) ReadByte () << 16
137
| (uint) ReadByte () << 8
141
public int ReadCompressedInt32 ()
143
var value = (int) ReadCompressedUInt32 ();
145
return (value & 1) != 0
150
public float ReadSingle ()
152
if (!BitConverter.IsLittleEndian) {
153
var bytes = ReadBytes (4);
154
Array.Reverse (bytes);
155
return BitConverter.ToSingle (bytes, 0);
158
float value = BitConverter.ToSingle (buffer, position);
163
public double ReadDouble ()
165
if (!BitConverter.IsLittleEndian) {
166
var bytes = ReadBytes (8);
167
Array.Reverse (bytes);
168
return BitConverter.ToDouble (bytes, 0);
171
double value = BitConverter.ToDouble (buffer, position);
178
public void WriteByte (byte value)
180
if (position == buffer.Length)
183
buffer [position++] = value;
185
if (position > length)
189
public void WriteSByte (sbyte value)
191
WriteByte ((byte) value);
194
public void WriteUInt16 (ushort value)
196
if (position + 2 > buffer.Length)
199
buffer [position++] = (byte) value;
200
buffer [position++] = (byte) (value >> 8);
202
if (position > length)
206
public void WriteInt16 (short value)
208
WriteUInt16 ((ushort) value);
211
public void WriteUInt32 (uint value)
213
if (position + 4 > buffer.Length)
216
buffer [position++] = (byte) value;
217
buffer [position++] = (byte) (value >> 8);
218
buffer [position++] = (byte) (value >> 16);
219
buffer [position++] = (byte) (value >> 24);
221
if (position > length)
225
public void WriteInt32 (int value)
227
WriteUInt32 ((uint) value);
230
public void WriteUInt64 (ulong value)
232
if (position + 8 > buffer.Length)
235
buffer [position++] = (byte) value;
236
buffer [position++] = (byte) (value >> 8);
237
buffer [position++] = (byte) (value >> 16);
238
buffer [position++] = (byte) (value >> 24);
239
buffer [position++] = (byte) (value >> 32);
240
buffer [position++] = (byte) (value >> 40);
241
buffer [position++] = (byte) (value >> 48);
242
buffer [position++] = (byte) (value >> 56);
244
if (position > length)
248
public void WriteInt64 (long value)
250
WriteUInt64 ((ulong) value);
253
public void WriteCompressedUInt32 (uint value)
256
WriteByte ((byte) value);
257
else if (value < 0x4000) {
258
WriteByte ((byte) (0x80 | (value >> 8)));
259
WriteByte ((byte) (value & 0xff));
261
WriteByte ((byte) ((value >> 24) | 0xc0));
262
WriteByte ((byte) ((value >> 16) & 0xff));
263
WriteByte ((byte) ((value >> 8) & 0xff));
264
WriteByte ((byte) (value & 0xff));
268
public void WriteCompressedInt32 (int value)
270
WriteCompressedUInt32 ((uint) ((value < 0) ? ((-value) << 1) | 1 : value << 1));
273
public void WriteBytes (byte [] bytes)
275
var length = bytes.Length;
276
if (position + length > buffer.Length)
279
Buffer.BlockCopy (bytes, 0, buffer, position, length);
282
if (position > this.length)
283
this.length = position;
286
public void WriteBytes (int length)
288
if (position + length > buffer.Length)
293
if (position > this.length)
294
this.length = position;
297
public void WriteBytes (ByteBuffer buffer)
299
if (position + buffer.length > this.buffer.Length)
300
Grow (buffer.length);
302
Buffer.BlockCopy (buffer.buffer, 0, this.buffer, position, buffer.length);
303
position += buffer.length;
305
if (position > this.length)
306
this.length = position;
309
public void WriteSingle (float value)
311
var bytes = BitConverter.GetBytes (value);
313
if (!BitConverter.IsLittleEndian)
314
Array.Reverse (bytes);
319
public void WriteDouble (double value)
321
var bytes = BitConverter.GetBytes (value);
323
if (!BitConverter.IsLittleEndian)
324
Array.Reverse (bytes);
329
void Grow (int desired)
331
var current = this.buffer;
332
var current_length = current.Length;
334
var buffer = new byte [System.Math.Max (current_length + desired, current_length * 2)];
335
Buffer.BlockCopy (current, 0, buffer, 0, current_length);
336
this.buffer = buffer;