Added hammock project to debug streaming issues
[pithos-ms-client] / trunk / hammock / src / net35 / ICSharpCode.SharpZipLib.Silverlight / Core / StreamUtils.cs
1 // StreamUtils.cs
2 //
3 // Copyright 2005 John Reilly
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 //
19 // Linking this library statically or dynamically with other modules is
20 // making a combined work based on this library.  Thus, the terms and
21 // conditions of the GNU General Public License cover the whole
22 // combination.
23 // 
24 // As a special exception, the copyright holders of this library give you
25 // permission to link this library with independent modules to produce an
26 // executable, regardless of the license terms of these independent
27 // modules, and to copy and distribute the resulting executable under
28 // terms of your choice, provided that you also meet, for each linked
29 // independent module, the terms and conditions of the license of that
30 // module.  An independent module is a module which is not derived from
31 // or based on this library.  If you modify this library, you may extend
32 // this exception to your version of the library, but you are not
33 // obligated to do so.  If you do not wish to do so, delete this
34 // exception statement from your version.
35
36 using System;
37 using System.IO;
38 using ICSharpCode.SharpZipLib.Silverlight.Core;
39
40 namespace ICSharpCode.SharpZipLib.Silverlight.Core
41 {
42     /// <summary>
43     /// Provides simple <see cref="Stream"/>" utilities.
44     /// </summary>
45     public static class StreamUtils
46     {
47         /// <summary>
48         /// Read from a <see cref="Stream"/> ensuring all the required data is read.
49         /// </summary>
50         /// <param name="stream">The stream to read.</param>
51         /// <param name="buffer">The buffer to fill.</param>
52         static public void ReadFully(Stream stream, byte[] buffer)
53         {
54             ReadFully(stream, buffer, 0, buffer.Length);
55         }
56
57         /// <summary>
58         /// Read from a <see cref="Stream"/>" ensuring all the required data is read.
59         /// </summary>
60         /// <param name="stream">The stream to read data from.</param>
61         /// <param name="buffer">The buffer to store data in.</param>
62         /// <param name="offset">The offset at which to begin storing data.</param>
63         /// <param name="count">The number of bytes of data to store.</param>
64         static public void ReadFully(Stream stream, byte[] buffer, int offset, int count)
65         {
66             if ( stream == null ) {
67                 throw new ArgumentNullException("stream");
68             }
69
70             if ( buffer == null ) {
71                 throw new ArgumentNullException("buffer");
72             }
73
74             // Offset can equal length when buffer and count are 0.
75             if ( (offset < 0) || (offset > buffer.Length) ) {
76                 throw new ArgumentOutOfRangeException("offset");
77             }
78
79             if ( (count < 0) || (offset + count > buffer.Length) ) {
80                 throw new ArgumentOutOfRangeException("count");
81             }
82
83             while ( count > 0 ) {
84                 int readCount = stream.Read(buffer, offset, count);
85                 if ( readCount <= 0 ) {
86                     throw new EndOfStreamException();
87                 }
88                 offset += readCount;
89                 count -= readCount;
90             }
91         }
92
93         /// <summary>
94         /// Copy the contents of one <see cref="Stream"/> to another.
95         /// </summary>
96         /// <param name="source">The stream to source data from.</param>
97         /// <param name="destination">The stream to write data to.</param>
98         /// <param name="buffer">The buffer to use during copying.</param>
99         /// <param name="progressHandler">The <see cref="ProgressHandler">progress handler delegate</see> to use.</param>
100         /// <param name="updateInterval">The minimum <see cref="TimeSpan"/> between progress updates.</param>
101         /// <param name="sender">The source for this event.</param>
102         /// <param name="name">The name to use with the event.</param>
103         static public void Copy(Stream source, Stream destination,
104                                 byte[] buffer, ProgressHandler progressHandler, TimeSpan updateInterval, object sender, string name)
105         {
106             if (source == null) {
107                 throw new ArgumentNullException("source");
108             }
109
110             if (destination == null) {
111                 throw new ArgumentNullException("destination");
112             }
113
114             if (buffer == null) {
115                 throw new ArgumentNullException("buffer");
116             }
117
118             // Ensure a reasonable size of buffer is used without being prohibitive.
119             if (buffer.Length < 128) {
120                 throw new ArgumentException("Buffer is too small", "buffer");
121             }
122
123             if (progressHandler == null) {
124                 throw new ArgumentNullException("progressHandler");
125             }
126
127             bool copying = true;
128
129             DateTime marker = DateTime.Now;
130             long processed = 0;
131             long target = 0;
132
133             if (source.CanSeek) {
134                 target = source.Length - source.Position;
135             }
136
137             // Always fire 0% progress..
138             var args = new ProgressEventArgs(name, processed, target);
139             progressHandler(sender, args);
140
141             bool completeFired = false;
142
143             while (copying) {
144                 int bytesRead = source.Read(buffer, 0, buffer.Length);
145                 if (bytesRead > 0) {
146                     processed += bytesRead;
147                     destination.Write(buffer, 0, bytesRead);
148                 }
149                 else {
150                     destination.Flush();
151                     copying = false;
152                 }
153
154                 if (DateTime.Now - marker > updateInterval) {
155                     completeFired = (processed == target);
156                     marker = DateTime.Now;
157                     args = new ProgressEventArgs(name, processed, target);
158                     progressHandler(sender, args);
159
160                     copying = args.ContinueRunning;
161                 }
162             }
163
164             if (!completeFired) {
165                 args = new ProgressEventArgs(name, processed, target);
166                 progressHandler(sender, args);
167             }
168         }
169
170         /// <summary>
171         /// Copy the contents of one <see cref="Stream"/> to another.
172         /// </summary>
173         /// <param name="source">The stream to source data from.</param>
174         /// <param name="destination">The stream to write data to.</param>
175         /// <param name="buffer">The buffer to use during copying.</param>
176         static public void Copy(Stream source, Stream destination, byte[] buffer)
177         {
178             if ( source == null ) {
179                 throw new ArgumentNullException("source");
180             }
181
182             if ( destination == null ) {
183                 throw new ArgumentNullException("destination");
184             }
185
186             if ( buffer == null ) {
187                 throw new ArgumentNullException("buffer");
188             }
189
190             // Ensure a reasonable size of buffer is used without being prohibitive.
191             if ( buffer.Length < 128 ) {
192                 throw new ArgumentException("Buffer is too small", "buffer");
193             }
194
195             bool copying = true;
196
197             while ( copying ) {
198                 int bytesRead = source.Read(buffer, 0, buffer.Length);
199                 if ( bytesRead > 0 ) {
200                     destination.Write(buffer, 0, bytesRead);
201                 }
202                 else {
203                     destination.Flush();
204                     copying = false;
205                 }
206             }
207         }
208     }
209 }