2 // System.IO.BinaryWriter
5 // Matt Kimball (matt@kimball.net)
6 // Marek Safar (marek.safar@gmail.com)
10 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
11 // Copyright 2011 Xamarin Inc.
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 using System.Globalization;
37 using System.Runtime.InteropServices;
42 public class BinaryWriter : IDisposable {
44 // Null is a BinaryWriter with no backing store.
45 public static readonly BinaryWriter Null = new BinaryWriter ();
47 protected Stream OutStream;
48 private Encoding m_encoding;
49 private byte [] buffer;
54 protected BinaryWriter() : this (Stream.Null, EncodingHelper.UTF8UnmarkedUnsafe)
58 public BinaryWriter(Stream output) : this(output, EncodingHelper.UTF8UnmarkedUnsafe)
62 readonly bool leave_open;
64 public BinaryWriter(Stream output, Encoding encoding)
65 : this (output, encoding, false)
69 public BinaryWriter(Stream output, Encoding encoding, bool leaveOpen)
72 throw new ArgumentNullException("output");
74 throw new ArgumentNullException("encoding");
76 throw new ArgumentException(Locale.GetText ("Stream does not support writing or already closed."));
78 leave_open = leaveOpen;
80 m_encoding = encoding;
81 buffer = new byte [16];
84 public virtual Stream BaseStream {
91 public virtual void Close() {
95 public void Dispose ()
100 protected virtual void Dispose (bool disposing)
102 if (disposing && OutStream != null && !leave_open)
110 public virtual void Flush() {
114 public virtual long Seek(int offset, SeekOrigin origin) {
116 return OutStream.Seek(offset, origin);
119 public virtual void Write(bool value) {
122 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
124 buffer [0] = (byte) (value ? 1 : 0);
125 OutStream.Write(buffer, 0, 1);
128 public virtual void Write(byte value) {
131 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
133 OutStream.WriteByte(value);
136 public virtual void Write(byte[] buffer) {
139 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
142 throw new ArgumentNullException("buffer");
143 OutStream.Write(buffer, 0, buffer.Length);
146 public virtual void Write(byte[] buffer, int index, int count) {
149 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
152 throw new ArgumentNullException("buffer");
153 OutStream.Write(buffer, index, count);
156 public virtual void Write(char ch) {
159 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
161 char[] dec = new char[1];
163 byte[] enc = m_encoding.GetBytes(dec, 0, 1);
164 OutStream.Write(enc, 0, enc.Length);
167 public virtual void Write(char[] chars) {
170 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
173 throw new ArgumentNullException("chars");
174 byte[] enc = m_encoding.GetBytes(chars, 0, chars.Length);
175 OutStream.Write(enc, 0, enc.Length);
178 public virtual void Write(char[] chars, int index, int count) {
181 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
184 throw new ArgumentNullException("chars");
185 byte[] enc = m_encoding.GetBytes(chars, index, count);
186 OutStream.Write(enc, 0, enc.Length);
189 unsafe public virtual void Write(decimal value) {
192 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
194 byte* value_ptr = (byte *)&value;
197 * decimal in stream is lo32, mi32, hi32, ss32
198 * but its internal structure si ss32, hi32, lo32, mi32
201 if (BitConverter.IsLittleEndian) {
202 for (int i = 0; i < 16; i++) {
204 buffer [i + 12] = value_ptr [i];
206 buffer [i + 4] = value_ptr [i];
208 buffer [i - 8] = value_ptr [i];
210 buffer [i - 8] = value_ptr [i];
213 for (int i = 0; i < 16; i++) {
215 buffer [15 - i] = value_ptr [i];
217 buffer [15 - i] = value_ptr [i];
219 buffer [11 - i] = value_ptr [i];
221 buffer [19 - i] = value_ptr [i];
225 OutStream.Write(buffer, 0, 16);
228 public virtual void Write(double value) {
231 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
233 OutStream.Write(BitConverterLE.GetBytes(value), 0, 8);
236 public virtual void Write(short value) {
239 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
241 buffer [0] = (byte) value;
242 buffer [1] = (byte) (value >> 8);
243 OutStream.Write(buffer, 0, 2);
246 public virtual void Write(int value) {
249 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
251 buffer [0] = (byte) value;
252 buffer [1] = (byte) (value >> 8);
253 buffer [2] = (byte) (value >> 16);
254 buffer [3] = (byte) (value >> 24);
255 OutStream.Write(buffer, 0, 4);
258 public virtual void Write(long value) {
261 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
263 for (int i = 0, sh = 0; i < 8; i++, sh += 8)
264 buffer [i] = (byte) (value >> sh);
265 OutStream.Write(buffer, 0, 8);
268 [CLSCompliant(false)]
269 public virtual void Write(sbyte value) {
272 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
274 buffer [0] = (byte) value;
275 OutStream.Write(buffer, 0, 1);
278 public virtual void Write(float value) {
281 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
283 OutStream.Write(BitConverterLE.GetBytes(value), 0, 4);
286 public virtual void Write(string value) {
289 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
291 int len = m_encoding.GetByteCount (value);
292 Write7BitEncodedInt (len);
294 if (stringBuffer == null) {
295 stringBuffer = new byte [512];
296 maxCharsPerRound = 512 / m_encoding.GetMaxByteCount (1);
300 int chrem = value.Length;
302 int cch = (chrem > maxCharsPerRound) ? maxCharsPerRound : chrem;
303 int blen = m_encoding.GetBytes (value, chpos, cch, stringBuffer, 0);
304 OutStream.Write (stringBuffer, 0, blen);
311 [CLSCompliant(false)]
312 public virtual void Write(ushort value) {
315 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
317 buffer [0] = (byte) value;
318 buffer [1] = (byte) (value >> 8);
319 OutStream.Write(buffer, 0, 2);
322 [CLSCompliant(false)]
323 public virtual void Write(uint value) {
326 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
328 buffer [0] = (byte) value;
329 buffer [1] = (byte) (value >> 8);
330 buffer [2] = (byte) (value >> 16);
331 buffer [3] = (byte) (value >> 24);
332 OutStream.Write(buffer, 0, 4);
335 [CLSCompliant(false)]
336 public virtual void Write(ulong value) {
339 throw new ObjectDisposedException ("BinaryWriter", "Cannot write to a closed BinaryWriter");
341 for (int i = 0, sh = 0; i < 8; i++, sh += 8)
342 buffer [i] = (byte) (value >> sh);
343 OutStream.Write(buffer, 0, 8);
346 protected void Write7BitEncodedInt(int value) {
348 int high = (value >> 7) & 0x01ffffff;
349 byte b = (byte)(value & 0x7f);
352 b = (byte)(b | 0x80);