1 // 2 // GioStream.cs - provide a System.IO.Stream api to [Input|Output]Streams 3 // 4 // Author(s): 5 // Stephane Delcroix <stephane@delcroix.org> 6 // Gabriel Burt <gabriel.burt@gmail.com> 7 // 8 // Copyright (c) 2008 Stephane Delcroix 9 // Copyright (c) 2010 Novell, Inc. 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 33 namespace GLib 34 { 35 public class GioStream : System.IO.Stream 36 { 37 object stream; 38 bool can_read; 39 bool can_seek; 40 bool can_write; 41 bool is_disposed; 42 GioStream(Uri uri, System.IO.FileMode mode)43 public GioStream (Uri uri, System.IO.FileMode mode) 44 { 45 throw new NotImplementedException (); 46 } 47 GioStream(string filename, System.IO.FileMode mode)48 public GioStream (string filename, System.IO.FileMode mode) 49 { 50 throw new NotImplementedException (); 51 } 52 GioStream(InputStream stream)53 public GioStream (InputStream stream) 54 { 55 this.stream = stream; 56 can_read = true; 57 can_seek = stream is Seekable && (stream as Seekable).CanSeek; 58 } 59 GioStream(OutputStream stream)60 public GioStream (OutputStream stream) 61 { 62 this.stream = stream; 63 can_write = true; 64 can_seek = stream is Seekable && (stream as Seekable).CanSeek; 65 } 66 67 #if GIO_SHARP_2_22 GioStream(IOStream stream)68 public GioStream (IOStream stream) 69 { 70 this.stream = stream; 71 can_read = true; 72 can_write = true; 73 can_seek = stream is Seekable && (stream as Seekable).CanSeek; 74 } 75 #endif 76 77 public override bool CanSeek { 78 get { return can_seek; } 79 } 80 81 public override bool CanRead { 82 get { return can_read; } 83 } 84 85 public override bool CanWrite { 86 get { return can_write; } 87 } 88 89 public override long Length { 90 get { 91 if (!CanSeek) 92 throw new NotSupportedException ("This stream doesn't support seeking"); 93 if (is_disposed) 94 throw new ObjectDisposedException ("The stream is closed"); 95 96 if (stream is FileInputStream) { 97 FileInfo info = (stream as FileInputStream).QueryInfo ("standard::size", null); 98 return info.Size; 99 } 100 if (stream is FileOutputStream) { 101 FileInfo info = (stream as FileOutputStream).QueryInfo ("standard::size", null); 102 return info.Size; 103 } 104 #if GIO_SHARP_2_22 105 if (stream is FileIOStream) { 106 FileInfo info = (stream as FileIOStream).QueryInfo ("standard::size", null); 107 return info.Size; 108 } 109 #endif 110 throw new NotImplementedException (String.Format ("not implemented for {0} streams", stream.GetType())); 111 } 112 } 113 114 public override long Position { 115 get { 116 if (!CanSeek) 117 throw new NotSupportedException ("This stream doesn't support seeking"); 118 if (is_disposed) 119 throw new ObjectDisposedException ("The stream is closed"); 120 return (stream as Seekable).Position; 121 } 122 set { 123 Seek (value, System.IO.SeekOrigin.Begin); 124 } 125 } 126 Flush()127 public override void Flush () 128 { 129 if (is_disposed) 130 throw new ObjectDisposedException ("The stream is closed"); 131 } 132 Read(byte[] buffer, int offset, int count)133 public override int Read (byte[] buffer, int offset, int count) 134 { 135 if (buffer == null) 136 throw new ArgumentNullException ("buffer"); 137 if (offset + count - 1 > buffer.Length) 138 throw new ArgumentException ("(offset + count - 1) is greater than the length of buffer"); 139 if (offset < 0) 140 throw new ArgumentOutOfRangeException ("offset"); 141 if (count < 0) 142 throw new ArgumentOutOfRangeException ("count"); 143 if (!CanRead) 144 throw new NotSupportedException ("The stream does not support reading"); 145 if (is_disposed) 146 throw new ObjectDisposedException ("The stream is closed"); 147 InputStream input_stream = null; 148 if (stream is InputStream) 149 input_stream = stream as InputStream; 150 #if GIO_SHARP_2_22 151 else if (stream is IOStream) 152 input_stream = (stream as IOStream).InputStream; 153 #endif 154 if (input_stream == null) 155 throw new System.Exception ("this shouldn't happen"); 156 157 if (offset == 0) 158 return (int)input_stream.Read (buffer, (ulong)count, null); 159 else { 160 byte[] buf = new byte[count]; 161 int ret = (int)input_stream.Read (buf, (ulong)count, null); 162 buf.CopyTo (buffer, offset); 163 return ret; 164 } 165 } 166 Write(byte[] buffer, int offset, int count)167 public override void Write (byte[] buffer, int offset, int count) 168 { 169 if (buffer == null) 170 throw new ArgumentNullException ("buffer"); 171 if (offset + count > buffer.Length) 172 throw new ArgumentException ("(offset + count) is greater than the length of buffer"); 173 if (offset < 0) 174 throw new ArgumentOutOfRangeException ("offset"); 175 if (count < 0) 176 throw new ArgumentOutOfRangeException ("count"); 177 if (!CanWrite) 178 throw new NotSupportedException ("The stream does not support writing"); 179 if (is_disposed) 180 throw new ObjectDisposedException ("The stream is closed"); 181 OutputStream output_stream = null; 182 if (stream is OutputStream) 183 output_stream = stream as OutputStream; 184 #if GIO_SHARP_2_22 185 else if (stream is IOStream) 186 output_stream = (stream as IOStream).OutputStream; 187 #endif 188 if (output_stream == null) 189 throw new System.Exception ("this shouldn't happen"); 190 if (offset == 0) { 191 output_stream.Write (buffer, (ulong)count, null); 192 return; 193 } else { 194 byte[] buf = new byte[count]; 195 Array.Copy (buffer, offset, buf, 0, count); 196 output_stream.Write (buf, (ulong)count, null); 197 return; 198 } 199 } 200 Seek(long offset, System.IO.SeekOrigin origin)201 public override long Seek (long offset, System.IO.SeekOrigin origin) 202 { 203 if (!CanSeek) 204 throw new NotSupportedException ("This stream doesn't support seeking"); 205 if (is_disposed) 206 throw new ObjectDisposedException ("The stream is closed"); 207 Seekable seekable = stream as Seekable; 208 209 SeekType seek_type; 210 switch (origin) { 211 case System.IO.SeekOrigin.Current: 212 seek_type = SeekType.Cur; 213 break; 214 case System.IO.SeekOrigin.End: 215 seek_type = SeekType.End; 216 break; 217 case System.IO.SeekOrigin.Begin: 218 default: 219 seek_type = SeekType.Set; 220 break; 221 } 222 seekable.Seek (offset, seek_type, null); 223 return Position; 224 } 225 SetLength(long value)226 public override void SetLength (long value) 227 { 228 if (!CanSeek || !CanWrite) 229 throw new NotSupportedException ("This stream doesn't support seeking"); 230 231 var seekable = stream as Seekable; 232 233 if (!seekable.CanTruncate ()) 234 throw new NotSupportedException ("This stream doesn't support truncating"); 235 236 if (is_disposed) 237 throw new ObjectDisposedException ("The stream is closed"); 238 239 seekable.Truncate (value, null); 240 } 241 Close()242 public override void Close () 243 { 244 if (stream is InputStream) 245 (stream as InputStream).Close (null); 246 if (stream is OutputStream) 247 (stream as OutputStream).Close (null); 248 #if GIO_SHARP_2_22 249 if (stream is IOStream) 250 (stream as IOStream).Close (null); 251 #endif 252 is_disposed = true; 253 } 254 } 255 } 256