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;