Add unit test for Database
[mono.git] / mcs / class / Mono.Cecil / Mono.Cecil.PE / ByteBuffer.cs
1 //
2 // ByteBuffer.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@gmail.com)
6 //
7 // Copyright (c) 2008 - 2010 Jb Evain
8 //
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:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
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.
27 //
28
29 using System;
30
31 namespace Mono.Cecil.PE {
32
33         class ByteBuffer {
34
35                 internal byte [] buffer;
36                 internal int length;
37                 internal int position;
38
39                 public ByteBuffer ()
40                 {
41                         this.buffer = Empty<byte>.Array;
42                 }
43
44                 public ByteBuffer (int length)
45                 {
46                         this.buffer = new byte [length];
47                 }
48
49                 public ByteBuffer (byte [] buffer)
50                 {
51                         this.buffer = buffer ?? Empty<byte>.Array;
52                         this.length = this.buffer.Length;
53                 }
54
55                 public void Reset (byte [] buffer)
56                 {
57                         this.buffer = buffer ?? Empty<byte>.Array;
58                         this.length = this.buffer.Length;
59                 }
60
61                 public void Advance (int length)
62                 {
63                         position += length;
64                 }
65
66                 public byte ReadByte ()
67                 {
68                         return buffer [position++];
69                 }
70
71                 public sbyte ReadSByte ()
72                 {
73                         return (sbyte) ReadByte ();
74                 }
75
76                 public byte [] ReadBytes (int length)
77                 {
78                         var bytes = new byte [length];
79                         Buffer.BlockCopy (buffer, position, bytes, 0, length);
80                         position += length;
81                         return bytes;
82                 }
83
84                 public ushort ReadUInt16 ()
85                 {
86                         ushort value = (ushort) (buffer [position]
87                                 | (buffer [position + 1] << 8));
88                         position += 2;
89                         return value;
90                 }
91
92                 public short ReadInt16 ()
93                 {
94                         return (short) ReadUInt16 ();
95                 }
96
97                 public uint ReadUInt32 ()
98                 {
99                         uint value = (uint) (buffer [position]
100                                 | (buffer [position + 1] << 8)
101                                 | (buffer [position + 2] << 16)
102                                 | (buffer [position + 3] << 24));
103                         position += 4;
104                         return value;
105                 }
106
107                 public int ReadInt32 ()
108                 {
109                         return (int) ReadUInt32 ();
110                 }
111
112                 public ulong ReadUInt64 ()
113                 {
114                         uint low = ReadUInt32 ();
115                         uint high = ReadUInt32 ();
116
117                         return (((ulong) high) << 32) | low;
118                 }
119
120                 public long ReadInt64 ()
121                 {
122                         return (long) ReadUInt64 ();
123                 }
124
125                 public uint ReadCompressedUInt32 ()
126                 {
127                         byte first = ReadByte ();
128                         if ((first & 0x80) == 0)
129                                 return first;
130
131                         if ((first & 0x40) == 0)
132                                 return ((uint) (first & ~0x80) << 8)
133                                         | ReadByte ();
134
135                         return ((uint) (first & ~0xc0) << 24)
136                                 | (uint) ReadByte () << 16
137                                 | (uint) ReadByte () << 8
138                                 | ReadByte ();
139                 }
140
141                 public int ReadCompressedInt32 ()
142                 {
143                         var value = (int) ReadCompressedUInt32 ();
144
145                         return (value & 1) != 0
146                                 ? -(value >> 1)
147                                 : value >> 1;
148                 }
149
150                 public float ReadSingle ()
151                 {
152                         if (!BitConverter.IsLittleEndian) {
153                                 var bytes = ReadBytes (4);
154                                 Array.Reverse (bytes);
155                                 return BitConverter.ToSingle (bytes, 0);
156                         }
157
158                         float value = BitConverter.ToSingle (buffer, position);
159                         position += 4;
160                         return value;
161                 }
162
163                 public double ReadDouble ()
164                 {
165                         if (!BitConverter.IsLittleEndian) {
166                                 var bytes = ReadBytes (8);
167                                 Array.Reverse (bytes);
168                                 return BitConverter.ToDouble (bytes, 0);
169                         }
170
171                         double value = BitConverter.ToDouble (buffer, position);
172                         position += 8;
173                         return value;
174                 }
175
176 #if !READ_ONLY
177
178                 public void WriteByte (byte value)
179                 {
180                         if (position == buffer.Length)
181                                 Grow (1);
182
183                         buffer [position++] = value;
184
185                         if (position > length)
186                                 length = position;
187                 }
188
189                 public void WriteSByte (sbyte value)
190                 {
191                         WriteByte ((byte) value);
192                 }
193
194                 public void WriteUInt16 (ushort value)
195                 {
196                         if (position + 2 > buffer.Length)
197                                 Grow (2);
198
199                         buffer [position++] = (byte) value;
200                         buffer [position++] = (byte) (value >> 8);
201
202                         if (position > length)
203                                 length = position;
204                 }
205
206                 public void WriteInt16 (short value)
207                 {
208                         WriteUInt16 ((ushort) value);
209                 }
210
211                 public void WriteUInt32 (uint value)
212                 {
213                         if (position + 4 > buffer.Length)
214                                 Grow (4);
215
216                         buffer [position++] = (byte) value;
217                         buffer [position++] = (byte) (value >> 8);
218                         buffer [position++] = (byte) (value >> 16);
219                         buffer [position++] = (byte) (value >> 24);
220
221                         if (position > length)
222                                 length = position;
223                 }
224
225                 public void WriteInt32 (int value)
226                 {
227                         WriteUInt32 ((uint) value);
228                 }
229
230                 public void WriteUInt64 (ulong value)
231                 {
232                         if (position + 8 > buffer.Length)
233                                 Grow (8);
234
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);
243
244                         if (position > length)
245                                 length = position;
246                 }
247
248                 public void WriteInt64 (long value)
249                 {
250                         WriteUInt64 ((ulong) value);
251                 }
252
253                 public void WriteCompressedUInt32 (uint value)
254                 {
255                         if (value < 0x80)
256                                 WriteByte ((byte) value);
257                         else if (value < 0x4000) {
258                                 WriteByte ((byte) (0x80 | (value >> 8)));
259                                 WriteByte ((byte) (value & 0xff));
260                         } else {
261                                 WriteByte ((byte) ((value >> 24) | 0xc0));
262                                 WriteByte ((byte) ((value >> 16) & 0xff));
263                                 WriteByte ((byte) ((value >> 8) & 0xff));
264                                 WriteByte ((byte) (value & 0xff));
265                         }
266                 }
267
268                 public void WriteCompressedInt32 (int value)
269                 {
270                         WriteCompressedUInt32 ((uint) ((value < 0) ? ((-value) << 1) | 1 : value << 1));
271                 }
272
273                 public void WriteBytes (byte [] bytes)
274                 {
275                         var length = bytes.Length;
276                         if (position + length > buffer.Length)
277                                 Grow (length);
278
279                         Buffer.BlockCopy (bytes, 0, buffer, position, length);
280                         position += length;
281
282                         if (position > this.length)
283                                 this.length = position;
284                 }
285
286                 public void WriteBytes (int length)
287                 {
288                         if (position + length > buffer.Length)
289                                 Grow (length);
290
291                         position += length;
292
293                         if (position > this.length)
294                                 this.length = position;
295                 }
296
297                 public void WriteBytes (ByteBuffer buffer)
298                 {
299                         if (position + buffer.length > this.buffer.Length)
300                                 Grow (buffer.length);
301
302                         Buffer.BlockCopy (buffer.buffer, 0, this.buffer, position, buffer.length);
303                         position += buffer.length;
304
305                         if (position > this.length)
306                                 this.length = position;
307                 }
308
309                 public void WriteSingle (float value)
310                 {
311                         var bytes = BitConverter.GetBytes (value);
312
313                         if (!BitConverter.IsLittleEndian)
314                                 Array.Reverse (bytes);
315
316                         WriteBytes (bytes);
317                 }
318
319                 public void WriteDouble (double value)
320                 {
321                         var bytes = BitConverter.GetBytes (value);
322
323                         if (!BitConverter.IsLittleEndian)
324                                 Array.Reverse (bytes);
325
326                         WriteBytes (bytes);
327                 }
328
329                 void Grow (int desired)
330                 {
331                         var current = this.buffer;
332                         var current_length = current.Length;
333
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;
337                 }
338
339 #endif
340
341         }
342 }