2003-12-28 Ben Maurer <bmaurer@users.sourceforge.net>
[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 using System;
9 using System.Text;
10 using System.Globalization;
11
12 namespace System.IO {
13         [Serializable]
14         public class BinaryWriter : IDisposable {
15
16                 // Null is a BinaryWriter with no backing store.
17                 public static readonly BinaryWriter Null;
18
19                 protected Stream OutStream;
20                 private Encoding m_encoding;
21                 private byte [] buffer;
22                 private bool disposed = false;
23
24                 static BinaryWriter() {
25                         Null = new BinaryWriter();
26                 }
27
28                 protected BinaryWriter() : this (Stream.Null, Encoding.UTF8Unmarked) {
29                 }
30
31                 public BinaryWriter(Stream output) : this(output, Encoding.UTF8Unmarked) {
32                 }
33
34                 public BinaryWriter(Stream output, Encoding encoding) {
35                         if (output == null || encoding == null) 
36                                 throw new ArgumentNullException(Locale.GetText ("Output or Encoding is a null reference."));
37                         if (!output.CanWrite)
38                                 throw new ArgumentException(Locale.GetText ("Stream does not support writing or already closed."));
39
40                         OutStream = output;
41                         m_encoding = encoding;
42                         buffer = new byte [16];
43                 }
44
45                 public virtual Stream BaseStream {
46                         get {
47                                 return OutStream;
48                         }
49                 }
50
51                 public virtual void Close() {
52                         Dispose (true);
53                 }
54
55                 void IDisposable.Dispose() {
56                         Dispose (true);
57                 }
58
59                 protected virtual void Dispose (bool disposing)
60                 {
61                         if (disposing && OutStream != null)
62                                 OutStream.Close();
63                         
64                         buffer = null;
65                         m_encoding = null;
66                         disposed = true;
67                 }
68
69                 public virtual void Flush() {
70                         OutStream.Flush();
71                 }
72
73                 public virtual long Seek(int offset, SeekOrigin origin) {
74
75                         return OutStream.Seek(offset, origin);
76                 }
77
78                 public virtual void Write(bool value) {
79
80                         if (disposed)
81                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
82
83                         buffer [0] = (byte) (value ? 1 : 0);
84                         OutStream.Write(buffer, 0, 1);
85                 }
86
87                 public virtual void Write(byte value) {
88
89                         if (disposed)
90                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
91
92                         OutStream.WriteByte(value);
93                 }
94
95                 public virtual void Write(byte[] value) {
96
97                         if (disposed)
98                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
99
100                         if (value == null)
101                                 throw new ArgumentNullException(Locale.GetText ("Byte buffer is a null reference."));
102                         OutStream.Write(value, 0, value.Length);
103                 }
104
105                 public virtual void Write(byte[] value, int offset, int length) {
106
107                         if (disposed)
108                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
109
110                         if (value == null)
111                                 throw new ArgumentNullException(Locale.GetText ("Byte buffer is a null reference."));
112                         OutStream.Write(value, offset, length);
113                 }
114
115                 public virtual void Write(char value) {
116
117                         if (disposed)
118                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
119
120                         char[] dec = new char[1];
121                         dec[0] = value;
122                         byte[] enc = m_encoding.GetBytes(dec, 0, 1);
123                         OutStream.Write(enc, 0, enc.Length);
124                 }
125                 
126                 public virtual void Write(char[] value) {
127
128                         if (disposed)
129                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
130
131                         if (value == null)
132                                 throw new ArgumentNullException(Locale.GetText ("Chars is a null reference."));
133                         byte[] enc = m_encoding.GetBytes(value, 0, value.Length);
134                         OutStream.Write(enc, 0, enc.Length);
135                 }
136
137                 public virtual void Write(char[] value, int offset, int length) {
138
139                         if (disposed)
140                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
141
142                         if (value == null)
143                                 throw new ArgumentNullException(Locale.GetText ("Chars is a null reference."));
144                         byte[] enc = m_encoding.GetBytes(value, offset, length);
145                         OutStream.Write(enc, 0, enc.Length);
146                 }
147
148                 unsafe public virtual void Write(decimal value) {
149
150                         if (disposed)
151                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
152
153                         byte* value_ptr = (byte *)&value;
154                         for (int i = 0; i < 16; i++) {
155
156                                 /*
157                                  * decimal in stream is lo32, mi32, hi32, ss32
158                                  * but its internal structure si ss32, hi32, lo32, mi32
159                                  */
160                                 if (i < 4) 
161                                         buffer [i + 12] = value_ptr [i];
162                                 else if (i < 8)
163                                         buffer [i + 4] = value_ptr [i];
164                                 else if (i < 12)
165                                         buffer [i - 8] = value_ptr [i];
166                                 else 
167                                         buffer [i - 8] = value_ptr [i];
168                         }
169
170                         OutStream.Write(buffer, 0, 16);
171                 }
172
173                 public virtual void Write(double value) {
174
175                         if (disposed)
176                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
177
178                         OutStream.Write(BitConverter.GetBytes(value), 0, 8);
179                 }
180                 
181                 public virtual void Write(short value) {
182
183                         if (disposed)
184                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
185
186                         buffer [0] = (byte) value;
187                         buffer [1] = (byte) (value >> 8);
188                         OutStream.Write(buffer, 0, 2);
189                 }
190                 
191                 public virtual void Write(int value) {
192
193                         if (disposed)
194                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
195
196                         buffer [0] = (byte) value;
197                         buffer [1] = (byte) (value >> 8);
198                         buffer [2] = (byte) (value >> 16);
199                         buffer [3] = (byte) (value >> 24);
200                         OutStream.Write(buffer, 0, 4);
201                 }
202
203                 public virtual void Write(long value) {
204
205                         if (disposed)
206                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
207
208                         for (int i = 0, sh = 0; i < 8; i++, sh += 8)
209                                 buffer [i] = (byte) (value >> sh);
210                         OutStream.Write(buffer, 0, 8);
211                 }
212
213                 [CLSCompliant(false)]
214                 public virtual void Write(sbyte value) {
215
216                         if (disposed)
217                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
218
219                         buffer [0] = (byte) value;
220                         OutStream.Write(buffer, 0, 1);
221                 }
222
223                 public virtual void Write(float value) {
224
225                         if (disposed)
226                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
227
228                         OutStream.Write(BitConverter.GetBytes(value), 0, 4);
229                 }
230
231                 byte [] stringBuffer;
232                 int maxCharsPerRound;
233                 
234                 public virtual void Write(string value) {
235
236                         if (disposed)
237                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
238
239                         int len = m_encoding.GetByteCount (value);
240                         Write7BitEncodedInt (len);
241                         
242                         if (stringBuffer == null) {
243                                 stringBuffer = new byte [512];
244                                 maxCharsPerRound = 512 / m_encoding.GetMaxByteCount (1);
245                         }
246                         
247                         int chpos = 0;
248                         int chrem = value.Length;
249                         while (chrem > 0) {
250                                 int cch = (chrem > maxCharsPerRound) ? maxCharsPerRound : chrem;
251                                 int blen = m_encoding.GetBytes (value, chpos, cch, stringBuffer, 0);
252                                 OutStream.Write (stringBuffer, 0, blen);
253                                 
254                                 chpos += cch;
255                                 chrem -= cch;
256                         }
257                 }
258
259                 [CLSCompliant(false)]
260                 public virtual void Write(ushort value) {
261
262                         if (disposed)
263                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
264
265                         buffer [0] = (byte) value;
266                         buffer [1] = (byte) (value >> 8);
267                         OutStream.Write(buffer, 0, 2);
268                 }
269
270                 [CLSCompliant(false)]
271                 public virtual void Write(uint value) {
272
273                         if (disposed)
274                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
275
276                         buffer [0] = (byte) value;
277                         buffer [1] = (byte) (value >> 8);
278                         buffer [2] = (byte) (value >> 16);
279                         buffer [3] = (byte) (value >> 24);
280                         OutStream.Write(buffer, 0, 4);
281                 }
282
283                 [CLSCompliant(false)]
284                 public virtual void Write(ulong value) {
285
286                         if (disposed)
287                                 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
288
289                         for (int i = 0, sh = 0; i < 8; i++, sh += 8)
290                                 buffer [i] = (byte) (value >> sh);
291                         OutStream.Write(buffer, 0, 8);
292                 }
293
294                 protected void Write7BitEncodedInt(int value) {
295                         do {
296                                 int high = (value >> 7) & 0x01ffffff;
297                                 byte b = (byte)(value & 0x7f);
298
299                                 if (high != 0) {
300                                         b = (byte)(b | 0x80);
301                                 }
302
303                                 Write(b);
304                                 value = high;
305                         } while(value != 0);
306                 }
307         }
308 }