|
1 | 1 | // Copyright Dirk Lemstra https://github.com/dlemstra/Magick.NET. |
2 | 2 | // Licensed under the Apache License, Version 2.0. |
3 | 3 |
|
4 | | -using System; |
5 | 4 | using System.IO; |
6 | | -using System.Runtime.InteropServices; |
7 | 5 |
|
8 | 6 | namespace ImageMagick; |
9 | 7 |
|
10 | | -internal sealed unsafe class StreamWrapper : IDisposable |
| 8 | +internal sealed class StreamWrapper : StreamWrapperBase |
11 | 9 | { |
12 | | - private const int BufferSize = 8192; |
13 | | - |
14 | | - private readonly PooledByteArray _buffer; |
15 | | - private readonly byte* _bufferStart; |
16 | | - private readonly long _streamStart; |
17 | | - private readonly GCHandle _handle; |
18 | | - private Stream _stream; |
| 10 | + private readonly Stream _stream; |
19 | 11 |
|
20 | 12 | private StreamWrapper(Stream stream) |
| 13 | + : base(stream) |
21 | 14 | { |
22 | 15 | _stream = stream; |
23 | | - _buffer = new PooledByteArray(BufferSize); |
24 | | - _handle = GCHandle.Alloc(_buffer.Data, GCHandleType.Pinned); |
25 | | - _bufferStart = (byte*)_handle.AddrOfPinnedObject().ToPointer(); |
26 | | - |
27 | | - try |
28 | | - { |
29 | | - _streamStart = _stream.Position; |
30 | | - } |
31 | | - catch |
32 | | - { |
33 | | - _streamStart = 0; |
34 | | - } |
35 | 16 | } |
36 | 17 |
|
37 | 18 | public static StreamWrapper CreateForReading(Stream stream) |
38 | 19 | { |
39 | 20 | Throw.IfFalse(stream.CanRead, nameof(stream), "The stream should be readable."); |
40 | 21 |
|
41 | | - return new StreamWrapper(stream); |
| 22 | + return new(stream); |
42 | 23 | } |
43 | 24 |
|
44 | 25 | public static StreamWrapper CreateForWriting(Stream stream) |
45 | 26 | { |
46 | 27 | Throw.IfFalse(stream.CanWrite, nameof(stream), "The stream should be writable."); |
47 | 28 |
|
48 | | - return new StreamWrapper(stream); |
49 | | - } |
50 | | - |
51 | | - public void Dispose() |
52 | | - { |
53 | | - _handle.Free(); |
54 | | - _buffer.Dispose(); |
| 29 | + return new(stream); |
55 | 30 | } |
56 | 31 |
|
57 | | - public long Read(IntPtr data, UIntPtr count, IntPtr user_data) |
58 | | - { |
59 | | - var total = (long)count; |
60 | | - if (total == 0) |
61 | | - return 0; |
62 | | - |
63 | | - if (data == IntPtr.Zero) |
64 | | - return 0; |
65 | | - |
66 | | - var destination = (byte*)data.ToPointer(); |
67 | | - long bytesRead = 0; |
68 | | - |
69 | | - while (total > 0) |
70 | | - { |
71 | | - var length = Math.Min(total, BufferSize); |
| 32 | + protected override int Read(int count) |
| 33 | + => _stream.Read(Data, 0, count); |
72 | 34 |
|
73 | | - try |
74 | | - { |
75 | | - length = _stream.Read(_buffer.Data, 0, (int)length); |
76 | | - } |
77 | | - catch |
78 | | - { |
79 | | - return -1; |
80 | | - } |
| 35 | + protected override long Seek(long offset, SeekOrigin origin) |
| 36 | + => _stream.Seek(offset, origin); |
81 | 37 |
|
82 | | - if (length == 0) |
83 | | - break; |
| 38 | + protected override long Tell() |
| 39 | + => _stream.Position; |
84 | 40 |
|
85 | | - bytesRead += length; |
86 | | - |
87 | | - destination = ReadBuffer(destination, length); |
88 | | - |
89 | | - total -= length; |
90 | | - } |
91 | | - |
92 | | - return bytesRead; |
93 | | - } |
94 | | - |
95 | | - public long Seek(long offset, IntPtr whence, IntPtr user_data) |
96 | | - { |
97 | | - try |
98 | | - { |
99 | | - return (SeekOrigin)whence switch |
100 | | - { |
101 | | - SeekOrigin.Begin => _stream.Seek(_streamStart + offset, SeekOrigin.Begin) - _streamStart, |
102 | | - SeekOrigin.Current => _stream.Seek(offset, SeekOrigin.Current) - _streamStart, |
103 | | - SeekOrigin.End => _stream.Seek(offset, SeekOrigin.End) - _streamStart, |
104 | | - _ => -1, |
105 | | - }; |
106 | | - } |
107 | | - catch |
108 | | - { |
109 | | - return -1; |
110 | | - } |
111 | | - } |
112 | | - |
113 | | - public long Tell(IntPtr user_data) |
114 | | - { |
115 | | - try |
116 | | - { |
117 | | - return _stream.Position - _streamStart; |
118 | | - } |
119 | | - catch |
120 | | - { |
121 | | - return -1; |
122 | | - } |
123 | | - } |
124 | | - |
125 | | - public long Write(IntPtr data, UIntPtr count, IntPtr user_data) |
126 | | - { |
127 | | - var total = (long)count; |
128 | | - if (total == 0) |
129 | | - return 0; |
130 | | - |
131 | | - if (data == IntPtr.Zero) |
132 | | - return 0; |
133 | | - |
134 | | - var source = (byte*)data.ToPointer(); |
135 | | - |
136 | | - while (total > 0) |
137 | | - { |
138 | | - var length = Math.Min(total, BufferSize); |
139 | | - |
140 | | - source = FillBuffer(source, length); |
141 | | - |
142 | | - try |
143 | | - { |
144 | | - _stream.Write(_buffer.Data, 0, (int)length); |
145 | | - } |
146 | | - catch |
147 | | - { |
148 | | - return -1; |
149 | | - } |
150 | | - |
151 | | - total -= length; |
152 | | - } |
153 | | - |
154 | | - return (long)count; |
155 | | - } |
156 | | - |
157 | | - private byte* FillBuffer(byte* source, long length) |
158 | | - { |
159 | | - NativeMemory.Copy(source, _bufferStart, length); |
160 | | - return source + length; |
161 | | - } |
162 | | - |
163 | | - private byte* ReadBuffer(byte* destination, long length) |
164 | | - { |
165 | | - NativeMemory.Copy(_bufferStart, destination, length); |
166 | | - return destination + length; |
167 | | - } |
| 41 | + protected override void Write(int count) |
| 42 | + => _stream.Write(Data, 0, count); |
168 | 43 | } |
0 commit comments