aboutsummaryrefslogtreecommitdiff
path: root/src/dtf/WixToolset.Dtf.Compression.Zip/ConcatStream.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/dtf/WixToolset.Dtf.Compression.Zip/ConcatStream.cs157
1 files changed, 157 insertions, 0 deletions
diff --git a/src/dtf/WixToolset.Dtf.Compression.Zip/ConcatStream.cs b/src/dtf/WixToolset.Dtf.Compression.Zip/ConcatStream.cs
new file mode 100644
index 00000000..20d675d9
--- /dev/null
+++ b/src/dtf/WixToolset.Dtf.Compression.Zip/ConcatStream.cs
@@ -0,0 +1,157 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.Dtf.Compression.Zip
4{
5 using System;
6 using System.IO;
7
8 /// <summary>
9 /// Used to trick a DeflateStream into reading from or writing to
10 /// a series of (chunked) streams instead of a single steream.
11 /// </summary>
12 internal class ConcatStream : Stream
13 {
14 private Stream source;
15 private long position;
16 private long length;
17 private Action<ConcatStream> nextStreamHandler;
18
19 public ConcatStream(Action<ConcatStream> nextStreamHandler)
20 {
21 if (nextStreamHandler == null)
22 {
23 throw new ArgumentNullException("nextStreamHandler");
24 }
25
26 this.nextStreamHandler = nextStreamHandler;
27 this.length = Int64.MaxValue;
28 }
29
30 public Stream Source
31 {
32 get { return this.source; }
33 set { this.source = value; }
34 }
35
36 public override bool CanRead
37 {
38 get { return true; }
39 }
40
41 public override bool CanWrite
42 {
43 get { return true; }
44 }
45
46 public override bool CanSeek
47 {
48 get { return false; }
49 }
50
51 public override long Length
52 {
53 get
54 {
55 return this.length;
56 }
57 }
58
59 public override long Position
60 {
61 get { return this.position; }
62 set { throw new NotSupportedException(); }
63 }
64
65 public override int Read(byte[] buffer, int offset, int count)
66 {
67 if (this.source == null)
68 {
69 this.nextStreamHandler(this);
70 }
71
72 count = (int) Math.Min(count, this.length - this.position);
73
74 int bytesRemaining = count;
75 while (bytesRemaining > 0)
76 {
77 if (this.source == null)
78 {
79 throw new InvalidOperationException();
80 }
81
82 int partialCount = (int) Math.Min(bytesRemaining,
83 this.source.Length - this.source.Position);
84
85 if (partialCount == 0)
86 {
87 this.nextStreamHandler(this);
88 continue;
89 }
90
91 partialCount = this.source.Read(
92 buffer, offset + count - bytesRemaining, partialCount);
93 bytesRemaining -= partialCount;
94 this.position += partialCount;
95 }
96
97 return count;
98 }
99
100 public override void Write(byte[] buffer, int offset, int count)
101 {
102 if (this.source == null)
103 {
104 this.nextStreamHandler(this);
105 }
106
107 int bytesRemaining = count;
108 while (bytesRemaining > 0)
109 {
110 if (this.source == null)
111 {
112 throw new InvalidOperationException();
113 }
114
115 int partialCount = (int) Math.Min(bytesRemaining,
116 Math.Max(0, this.length - this.source.Position));
117
118 if (partialCount == 0)
119 {
120 this.nextStreamHandler(this);
121 continue;
122 }
123
124 this.source.Write(
125 buffer, offset + count - bytesRemaining, partialCount);
126 bytesRemaining -= partialCount;
127 this.position += partialCount;
128 }
129 }
130
131 public override void Flush()
132 {
133 if (this.source != null)
134 {
135 this.source.Flush();
136 }
137 }
138
139 public override long Seek(long offset, SeekOrigin origin)
140 {
141 throw new NotSupportedException();
142 }
143
144 public override void SetLength(long value)
145 {
146 this.length = value;
147 }
148
149 public override void Close()
150 {
151 if (this.source != null)
152 {
153 this.source.Close();
154 }
155 }
156 }
157}