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  *
7  * Copyright (c) 2008 Novell, Inc.
8  *
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining
11  * a copy of this software and associated documentation files (the
12  * "Software"), to deal in the Software without restriction, including
13  * without limitation the rights to use, copy, modify, merge, publish,
14  * distribute, sublicense, and/or sell copies of the Software, and to
15  * permit persons to whom the Software is furnished to do so, subject to
16  * the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be
19  * included in all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28  *
29  */
30 using System;
31 
32 namespace GLib
33 {
34 	public class GioStream : System.IO.Stream
35 	{
36 		object stream;
37 		bool can_read;
38 		bool can_seek;
39 		bool can_write;
40 		bool is_disposed;
41 
GioStream(Uri uri, System.IO.FileMode mode)42 		public GioStream (Uri uri, System.IO.FileMode mode)
43 		{
44 			throw new NotImplementedException ();
45 		}
46 
GioStream(string filename, System.IO.FileMode mode)47 		public GioStream (string filename, System.IO.FileMode mode)
48 		{
49 			throw new NotImplementedException ();
50 		}
51 
GioStream(InputStream stream)52 		public GioStream (InputStream stream)
53 		{
54 			this.stream = stream;
55 			can_read = true;
56 			can_seek = stream is ISeekable && (stream as ISeekable).CanSeek;
57 		}
58 
GioStream(OutputStream stream)59 		public GioStream (OutputStream stream)
60 		{
61 			this.stream = stream;
62 			can_write = true;
63 			can_seek = stream is ISeekable && (stream as ISeekable).CanSeek;
64 		}
65 
GioStream(IOStream stream)66 		public GioStream (IOStream stream)
67 		{
68 			this.stream = stream;
69 			can_read = true;
70 			can_write = true;
71 			can_seek = stream is ISeekable && (stream as ISeekable).CanSeek;
72 		}
73 
74 		public override bool CanSeek {
75 			get { return can_seek; }
76 		}
77 
78 		public override bool CanRead {
79 			get { return can_read; }
80 		}
81 
82 		public override bool CanWrite {
83 			get { return can_write; }
84 		}
85 
86 		public override long Length {
87 			get {
88 				if (!CanSeek)
89 					throw new NotSupportedException ("This stream doesn't support seeking");
90 				if (is_disposed)
91 					throw new ObjectDisposedException ("The stream is closed");
92 
93 				if (stream is FileInputStream) {
94 					FileInfo info = (stream as FileInputStream).QueryInfo ("standard::size", null);
95 					return info.Size;
96 				}
97 				if (stream is FileOutputStream) {
98 					FileInfo info = (stream as FileOutputStream).QueryInfo ("standard::size", null);
99 					return info.Size;
100 				}
101 				if (stream is FileIOStream) {
102 					FileInfo info = (stream as FileIOStream).QueryInfo ("standard::size", null);
103 					return info.Size;
104 				}
105 				throw new NotImplementedException (String.Format ("not implemented for {0} streams", stream.GetType()));
106 			}
107 		}
108 
109 		public override long Position {
110 			get {
111 				if (!CanSeek)
112 					throw new NotSupportedException ("This stream doesn't support seeking");
113 				if (is_disposed)
114 					throw new ObjectDisposedException ("The stream is closed");
115 				return (stream as ISeekable).Position;
116 			}
117 			set {
118 				Seek (value, System.IO.SeekOrigin.Begin);
119 			}
120 		}
121 
Flush()122 		public override void Flush ()
123 		{
124 			if (is_disposed)
125 				throw new ObjectDisposedException ("The stream is closed");
126 		}
127 
Read(byte[] buffer, int offset, int count)128 		public override int Read (byte[] buffer, int offset, int count)
129 		{
130 			if (buffer == null)
131 				throw new ArgumentNullException ("buffer");
132 			if (offset + count - 1 > buffer.Length)
133 				throw new ArgumentException ("(offset + count - 1) is greater than the length of buffer");
134 			if (offset < 0)
135 				throw new ArgumentOutOfRangeException ("offset");
136 			if (count < 0)
137 				throw new ArgumentOutOfRangeException ("count");
138 			if (!CanRead)
139 				throw new NotSupportedException ("The stream does not support reading");
140 			if (is_disposed)
141 				throw new ObjectDisposedException ("The stream is closed");
142 			InputStream input_stream = null;
143 			if (stream is InputStream)
144 				input_stream = stream as InputStream;
145 			else if (stream is IOStream)
146 				input_stream = (stream as IOStream).InputStream;
147 			if (input_stream == null)
148 				throw new System.Exception ("this shouldn't happen");
149 
150 			if (offset == 0)
151 				return (int)input_stream.Read (buffer, (ulong)count, null);
152 			else {
153 				byte[] buf = new byte[count];
154 				int ret = (int)input_stream.Read (buf, (ulong)count, null);
155 				buf.CopyTo (buffer, offset);
156 				return ret;
157 			}
158 		}
159 
Write(byte[] buffer, int offset, int count)160 		public override void Write (byte[] buffer, int offset, int count)
161 		{
162 			if (buffer == null)
163 				throw new ArgumentNullException ("buffer");
164 			if (offset + count  > buffer.Length)
165 				throw new ArgumentException ("(offset + count) is greater than the length of buffer");
166 			if (offset < 0)
167 				throw new ArgumentOutOfRangeException ("offset");
168 			if (count < 0)
169 				throw new ArgumentOutOfRangeException ("count");
170 			if (!CanWrite)
171 				throw new NotSupportedException ("The stream does not support writing");
172 			if (is_disposed)
173 				throw new ObjectDisposedException ("The stream is closed");
174 			OutputStream output_stream = null;
175 			if (stream is OutputStream)
176 				output_stream = stream as OutputStream;
177 			else if (stream is IOStream)
178 				output_stream = (stream as IOStream).OutputStream;
179 			if (output_stream == null)
180 				throw new System.Exception ("this shouldn't happen");
181 			if (offset == 0) {
182 				output_stream.Write (buffer, (ulong)count, null);
183 				return;
184 			} else {
185 				byte[] buf = new byte[count];
186 				Array.Copy (buffer, offset, buf, 0, count);
187 				output_stream.Write (buf, (ulong)count, null);
188 				return;
189 			}
190 		}
191 
Seek(long offset, System.IO.SeekOrigin origin)192 		public override long Seek (long offset, System.IO.SeekOrigin origin)
193 		{
194 			if (!CanSeek)
195 				throw new NotSupportedException ("This stream doesn't support seeking");
196 			if (is_disposed)
197 				throw new ObjectDisposedException ("The stream is closed");
198 			var seekable = stream as ISeekable;
199 
200 			SeekType seek_type;
201 			switch (origin) {
202 			case System.IO.SeekOrigin.Current:
203 				seek_type = SeekType.Cur;
204 				break;
205 			case System.IO.SeekOrigin.End:
206 				seek_type = SeekType.End;
207 				break;
208 			case System.IO.SeekOrigin.Begin:
209 			default:
210 				seek_type = SeekType.Set;
211 				break;
212 			}
213 			seekable.Seek (offset, seek_type, null);
214 			return Position;
215 		}
216 
SetLength(long value)217 		public override void SetLength (long value)
218 		{
219 			if (!CanSeek || !CanWrite)
220 				throw new NotSupportedException ("This stream doesn't support seeking");
221 
222 			var seekable = stream as ISeekable;
223 
224 			if (!seekable.CanTruncate ())
225 				throw new NotSupportedException ("This stream doesn't support truncating");
226 
227 			if (is_disposed)
228 				throw new ObjectDisposedException ("The stream is closed");
229 
230 			seekable.Truncate (value, null);
231 		}
232 
Close()233 		public override void Close ()
234 		{
235 			if (stream is InputStream)
236 				(stream as InputStream).Close (null);
237 			if (stream is OutputStream)
238 				(stream as OutputStream).Close (null);
239 			if (stream is IOStream)
240 				(stream as IOStream).Close (null);
241 			is_disposed = true;
242 		}
243 	}
244 }
245