Statistics
| Branch: | Revision:

root / trunk / hammock / src / net35 / ICSharpCode.SharpZipLib.Silverlight / Core / StreamUtils.cs @ 0eea575a

History | View | Annotate | Download (8 kB)

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
}