2 // System.IO.BinaryWriter
5 // Matt Kimball (matt@kimball.net)
9 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
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:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
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.
33 using System.Globalization;
36 using System.Runtime.InteropServices;
44 public class BinaryWriter : IDisposable {
46 // Null is a BinaryWriter with no backing store.
47 public static readonly BinaryWriter Null = new BinaryWriter ();
49 protected Stream OutStream;
50 private Encoding m_encoding;
51 private byte [] buffer;
52 private bool disposed = false;
54 protected BinaryWriter() : this (Stream.Null, Encoding.UTF8UnmarkedUnsafe) {
57 public BinaryWriter(Stream output) : this(output, Encoding.UTF8UnmarkedUnsafe) {
60 public BinaryWriter(Stream output, Encoding encoding) {
62 throw new ArgumentNullException("output");
64 throw new ArgumentNullException("encoding");
66 throw new ArgumentException(Locale.GetText ("Stream does not support writing or already closed."));
69 m_encoding = encoding;
70 buffer = new byte [16];
73 public virtual Stream BaseStream {
79 public virtual void Close() {
83 void IDisposable.Dispose() {
87 protected virtual void Dispose (bool disposing)
89 if (disposing && OutStream != null)
97 public virtual void Flush() {
101 public virtual long Seek(int offset, SeekOrigin origin) {
103 return OutStream.Seek(offset, origin);
106 public virtual void Write(bool value) {
109 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
111 buffer [0] = (byte) (value ? 1 : 0);
112 OutStream.Write(buffer, 0, 1);
115 public virtual void Write(byte value) {
118 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
120 OutStream.WriteByte(value);
123 public virtual void Write(byte[] buffer) {
126 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
129 throw new ArgumentNullException("buffer");
130 OutStream.Write(buffer, 0, buffer.Length);
133 public virtual void Write(byte[] buffer, int index, int count) {
136 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
139 throw new ArgumentNullException("buffer");
140 OutStream.Write(buffer, index, count);
143 public virtual void Write(char ch) {
146 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
148 char[] dec = new char[1];
150 byte[] enc = m_encoding.GetBytes(dec, 0, 1);
151 OutStream.Write(enc, 0, enc.Length);
154 public virtual void Write(char[] chars) {
157 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
160 throw new ArgumentNullException("chars");
161 byte[] enc = m_encoding.GetBytes(chars, 0, chars.Length);
162 OutStream.Write(enc, 0, enc.Length);
165 public virtual void Write(char[] chars, int index, int count) {
168 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
171 throw new ArgumentNullException("chars");
172 byte[] enc = m_encoding.GetBytes(chars, index, count);
173 OutStream.Write(enc, 0, enc.Length);
176 unsafe public virtual void Write(decimal value) {
179 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
181 byte* value_ptr = (byte *)&value;
184 * decimal in stream is lo32, mi32, hi32, ss32
185 * but its internal structure si ss32, hi32, lo32, mi32
188 if (BitConverter.IsLittleEndian) {
189 for (int i = 0; i < 16; i++) {
191 buffer [i + 12] = value_ptr [i];
193 buffer [i + 4] = value_ptr [i];
195 buffer [i - 8] = value_ptr [i];
197 buffer [i - 8] = value_ptr [i];
200 for (int i = 0; i < 16; i++) {
202 buffer [15 - i] = value_ptr [i];
204 buffer [15 - i] = value_ptr [i];
206 buffer [11 - i] = value_ptr [i];
208 buffer [19 - i] = value_ptr [i];
212 OutStream.Write(buffer, 0, 16);
215 public virtual void Write(double value) {
218 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
220 OutStream.Write(BitConverterLE.GetBytes(value), 0, 8);
223 public virtual void Write(short value) {
226 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
228 buffer [0] = (byte) value;
229 buffer [1] = (byte) (value >> 8);
230 OutStream.Write(buffer, 0, 2);
233 public virtual void Write(int value) {
236 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
238 buffer [0] = (byte) value;
239 buffer [1] = (byte) (value >> 8);
240 buffer [2] = (byte) (value >> 16);
241 buffer [3] = (byte) (value >> 24);
242 OutStream.Write(buffer, 0, 4);
245 public virtual void Write(long value) {
248 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
250 for (int i = 0, sh = 0; i < 8; i++, sh += 8)
251 buffer [i] = (byte) (value >> sh);
252 OutStream.Write(buffer, 0, 8);
255 [CLSCompliant(false)]
256 public virtual void Write(sbyte value) {
259 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
261 buffer [0] = (byte) value;
262 OutStream.Write(buffer, 0, 1);
265 public virtual void Write(float value) {
268 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
270 OutStream.Write(BitConverterLE.GetBytes(value), 0, 4);
273 byte [] stringBuffer;
274 int maxCharsPerRound;
276 public virtual void Write(string value) {
279 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
281 int len = m_encoding.GetByteCount (value);
282 Write7BitEncodedInt (len);
284 if (stringBuffer == null) {
285 stringBuffer = new byte [512];
286 maxCharsPerRound = 512 / m_encoding.GetMaxByteCount (1);
290 int chrem = value.Length;
292 int cch = (chrem > maxCharsPerRound) ? maxCharsPerRound : chrem;
293 int blen = m_encoding.GetBytes (value, chpos, cch, stringBuffer, 0);
294 OutStream.Write (stringBuffer, 0, blen);
301 [CLSCompliant(false)]
302 public virtual void Write(ushort value) {
305 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
307 buffer [0] = (byte) value;
308 buffer [1] = (byte) (value >> 8);
309 OutStream.Write(buffer, 0, 2);
312 [CLSCompliant(false)]
313 public virtual void Write(uint value) {
316 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
318 buffer [0] = (byte) value;
319 buffer [1] = (byte) (value >> 8);
320 buffer [2] = (byte) (value >> 16);
321 buffer [3] = (byte) (value >> 24);
322 OutStream.Write(buffer, 0, 4);
325 [CLSCompliant(false)]
326 public virtual void Write(ulong value) {
329 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
331 for (int i = 0, sh = 0; i < 8; i++, sh += 8)
332 buffer [i] = (byte) (value >> sh);
333 OutStream.Write(buffer, 0, 8);
336 protected void Write7BitEncodedInt(int value) {
338 int high = (value >> 7) & 0x01ffffff;
339 byte b = (byte)(value & 0x7f);
342 b = (byte)(b | 0x80);