New test.
[mono.git] / mcs / class / corlib / System.IO / BinaryWriter.cs
1 //
2 // System.IO.BinaryWriter
3 //
4 // Author:
5 //   Matt Kimball (matt@kimball.net)
6 //
7
8 //
9 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System;
32 using System.Text;
33 using System.Globalization;
34 using Mono.Security;
35
36 namespace System.IO {
37         [Serializable]
38         public class BinaryWriter : IDisposable {
39
40                 // Null is a BinaryWriter with no backing store.
41                 public static readonly BinaryWriter Null = new BinaryWriter ();
42
43                 protected Stream OutStream;
44                 private Encoding m_encoding;
45                 private byte [] buffer;
46                 private bool disposed = false;
47
48                 protected BinaryWriter() : this (Stream.Null, Encoding.UTF8Unmarked) {
49                 }
50
51                 public BinaryWriter(Stream output) : this(output, Encoding.UTF8Unmarked) {
52                 }
53
54                 public BinaryWriter(Stream output, Encoding encoding) {
55                         if (output == null || encoding == null) 
56                                 throw new ArgumentNullException(Locale.GetText ("Output or Encoding is a null reference."));
57                         if (!output.CanWrite)
58                                 throw new ArgumentException(Locale.GetText ("Stream does not support writing or already closed."));
59
60                         OutStream = output;
61                         m_encoding = encoding;
62                         buffer = new byte [16];
63                 }
64
65                 public virtual Stream BaseStream {
66                         get {
67                                 return OutStream;
68                         }
69                 }
70
71                 public virtual void Close() {
72                         Dispose (true);
73                 }
74
75                 void IDisposable.Dispose() {
76                         Dispose (true);
77                 }
78
79                 protected virtual void Dispose (bool disposing)
80                 {
81                         if (disposing && OutStream != null)
82                                 OutStream.Close();
83                         
84                         buffer = null;
85                         m_encoding = null;
86                         disposed = true;
87                 }
88
89                 public virtual void Flush() {
90                         OutStream.Flush();
91                 }
92
93                 public virtual long Seek(int offset, SeekOrigin origin) {
94
95                         return OutStream.Seek(offset, origin);
96                 }
97
98                 public virtual void Write(bool value) {
99
100                         if (disposed)
101                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
102
103                         buffer [0] = (byte) (value ? 1 : 0);
104                         OutStream.Write(buffer, 0, 1);
105                 }
106
107                 public virtual void Write(byte value) {
108
109                         if (disposed)
110                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
111
112                         OutStream.WriteByte(value);
113                 }
114
115                 public virtual void Write(byte[] value) {
116
117                         if (disposed)
118                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
119
120                         if (value == null)
121                                 throw new ArgumentNullException(Locale.GetText ("Byte buffer is a null reference."));
122                         OutStream.Write(value, 0, value.Length);
123                 }
124
125                 public virtual void Write(byte[] value, int offset, int length) {
126
127                         if (disposed)
128                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
129
130                         if (value == null)
131                                 throw new ArgumentNullException(Locale.GetText ("Byte buffer is a null reference."));
132                         OutStream.Write(value, offset, length);
133                 }
134
135                 public virtual void Write(char value) {
136
137                         if (disposed)
138                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
139
140                         char[] dec = new char[1];
141                         dec[0] = value;
142                         byte[] enc = m_encoding.GetBytes(dec, 0, 1);
143                         OutStream.Write(enc, 0, enc.Length);
144                 }
145                 
146                 public virtual void Write(char[] value) {
147
148                         if (disposed)
149                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
150
151                         if (value == null)
152                                 throw new ArgumentNullException(Locale.GetText ("Chars is a null reference."));
153                         byte[] enc = m_encoding.GetBytes(value, 0, value.Length);
154                         OutStream.Write(enc, 0, enc.Length);
155                 }
156
157                 public virtual void Write(char[] value, int offset, int length) {
158
159                         if (disposed)
160                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
161
162                         if (value == null)
163                                 throw new ArgumentNullException(Locale.GetText ("Chars is a null reference."));
164                         byte[] enc = m_encoding.GetBytes(value, offset, length);
165                         OutStream.Write(enc, 0, enc.Length);
166                 }
167
168                 unsafe public virtual void Write(decimal value) {
169
170                         if (disposed)
171                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
172
173                         byte* value_ptr = (byte *)&value;
174                         
175                         /*
176                          * decimal in stream is lo32, mi32, hi32, ss32
177                          * but its internal structure si ss32, hi32, lo32, mi32
178                          */
179                                  
180                         if (BitConverter.IsLittleEndian) {
181                                 for (int i = 0; i < 16; i++) {
182                                         if (i < 4) 
183                                                 buffer [i + 12] = value_ptr [i];
184                                         else if (i < 8)
185                                                 buffer [i + 4] = value_ptr [i];
186                                         else if (i < 12)
187                                                 buffer [i - 8] = value_ptr [i];
188                                         else 
189                                                 buffer [i - 8] = value_ptr [i];
190                                 }
191                         } else {
192                                 for (int i = 0; i < 16; i++) {
193                                         if (i < 4) 
194                                                 buffer [15 - i] = value_ptr [i];
195                                         else if (i < 8)
196                                                 buffer [15 - i] = value_ptr [i];
197                                         else if (i < 12)
198                                                 buffer [11 - i] = value_ptr [i];
199                                         else 
200                                                 buffer [19 - i] = value_ptr [i];
201                                 }
202                         }
203
204                         OutStream.Write(buffer, 0, 16);
205                 }
206
207                 public virtual void Write(double value) {
208
209                         if (disposed)
210                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
211
212                         OutStream.Write(BitConverterLE.GetBytes(value), 0, 8);
213                 }
214                 
215                 public virtual void Write(short value) {
216
217                         if (disposed)
218                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
219
220                         buffer [0] = (byte) value;
221                         buffer [1] = (byte) (value >> 8);
222                         OutStream.Write(buffer, 0, 2);
223                 }
224                 
225                 public virtual void Write(int value) {
226
227                         if (disposed)
228                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
229
230                         buffer [0] = (byte) value;
231                         buffer [1] = (byte) (value >> 8);
232                         buffer [2] = (byte) (value >> 16);
233                         buffer [3] = (byte) (value >> 24);
234                         OutStream.Write(buffer, 0, 4);
235                 }
236
237                 public virtual void Write(long value) {
238
239                         if (disposed)
240                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
241
242                         for (int i = 0, sh = 0; i < 8; i++, sh += 8)
243                                 buffer [i] = (byte) (value >> sh);
244                         OutStream.Write(buffer, 0, 8);
245                 }
246
247                 [CLSCompliant(false)]
248                 public virtual void Write(sbyte value) {
249
250                         if (disposed)
251                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
252
253                         buffer [0] = (byte) value;
254                         OutStream.Write(buffer, 0, 1);
255                 }
256
257                 public virtual void Write(float value) {
258
259                         if (disposed)
260                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
261
262                         OutStream.Write(BitConverterLE.GetBytes(value), 0, 4);
263                 }
264
265                 byte [] stringBuffer;
266                 int maxCharsPerRound;
267                 
268                 public virtual void Write(string value) {
269
270                         if (disposed)
271                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
272
273                         int len = m_encoding.GetByteCount (value);
274                         Write7BitEncodedInt (len);
275                         
276                         if (stringBuffer == null) {
277                                 stringBuffer = new byte [512];
278                                 maxCharsPerRound = 512 / m_encoding.GetMaxByteCount (1);
279                         }
280                         
281                         int chpos = 0;
282                         int chrem = value.Length;
283                         while (chrem > 0) {
284                                 int cch = (chrem > maxCharsPerRound) ? maxCharsPerRound : chrem;
285                                 int blen = m_encoding.GetBytes (value, chpos, cch, stringBuffer, 0);
286                                 OutStream.Write (stringBuffer, 0, blen);
287                                 
288                                 chpos += cch;
289                                 chrem -= cch;
290                         }
291                 }
292
293                 [CLSCompliant(false)]
294                 public virtual void Write(ushort value) {
295
296                         if (disposed)
297                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
298
299                         buffer [0] = (byte) value;
300                         buffer [1] = (byte) (value >> 8);
301                         OutStream.Write(buffer, 0, 2);
302                 }
303
304                 [CLSCompliant(false)]
305                 public virtual void Write(uint value) {
306
307                         if (disposed)
308                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
309
310                         buffer [0] = (byte) value;
311                         buffer [1] = (byte) (value >> 8);
312                         buffer [2] = (byte) (value >> 16);
313                         buffer [3] = (byte) (value >> 24);
314                         OutStream.Write(buffer, 0, 4);
315                 }
316
317                 [CLSCompliant(false)]
318                 public virtual void Write(ulong value) {
319
320                         if (disposed)
321                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
322
323                         for (int i = 0, sh = 0; i < 8; i++, sh += 8)
324                                 buffer [i] = (byte) (value >> sh);
325                         OutStream.Write(buffer, 0, 8);
326                 }
327
328                 protected void Write7BitEncodedInt(int value) {
329                         do {
330                                 int high = (value >> 7) & 0x01ffffff;
331                                 byte b = (byte)(value & 0x7f);
332
333                                 if (high != 0) {
334                                         b = (byte)(b | 0x80);
335                                 }
336
337                                 Write(b);
338                                 value = high;
339                         } while(value != 0);
340                 }
341         }
342 }