1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 
  8 namespace System.IO
  9 {
 10     public class IOBuffer
 11     {
 12         public nothrow IOBuffer(long size_) : size(size_)mem(null)
 13         {
 14         #if (MEM_DEBUG)
 15             mem = MemAlloc(sizetypename(*this));
 16         #else
 17             mem = MemAlloc(size);
 18         #endif
 19         }
 20         suppress IOBuffer(const IOBuffer&);
 21         suppress void operator=(const IOBuffer&);
 22         public nothrow IOBuffer(IOBuffer&& that) : size(that.size)mem(that.mem)
 23         {
 24             that.size = 0;
 25             that.mem = null;
 26         }
 27         public default nothrow void operator=(IOBuffer&& that);
 28         public ~IOBuffer()
 29         {
 30             if (mem != null)
 31             {
 32                 MemFree(mem);
 33             }
 34         }
 35         public inline nothrow long Size() const
 36         {
 37             return size;
 38         }
 39         public inline nothrow void* Mem() const
 40         {
 41             return mem;
 42         }
 43         public inline byte operator[](long index) const
 44         {
 45             if (index < 0 || index >= size)
 46             {
 47                 ThrowIndexOutOfBoundsException();
 48             }
 49             return cast<byte*>(mem)[index];
 50         }
 51         public inline nothrow byte& operator[](long index)
 52         {
 53             return cast<byte*>(mem)[index];
 54         }
 55         private long size;
 56         private void* mem;
 57     }
 58 
 59     public class BufferedByteStream : ByteStream
 60     {
 61         public nothrow BufferedByteStream(const SharedPtr<ByteStream>& baseStream_) : this(baseStream_4096)
 62         {
 63         }
 64         public nothrow BufferedByteStream(const SharedPtr<ByteStream>& baseStream_long bufferSize_) : 
 65             baseStream(baseStream_)buffer(bufferSize_)pos(buffer.Size())bytesAvailable(0)end(0)
 66         {
 67         }
 68         suppress BufferedByteStream(const BufferedByteStream&);
 69         suppress void operator=(const BufferedByteStream&);
 70         public override ~BufferedByteStream()
 71         {
 72             try
 73             {
 74                 if (!baseStream.IsNull())
 75                 {
 76                     Flush();
 77                 }
 78             }
 79             catch (const Exception&)
 80             {
 81             }
 82         }
 83         public override int ReadByte()
 84         {
 85             Flush();
 86             if (bytesAvailable == 0)
 87             {
 88                 FillBuf();
 89                 if (bytesAvailable == 0)
 90                 {
 91                     return -1;
 92                 }
 93             }
 94             byte value = buffer[pos++];
 95             --bytesAvailable;
 96             return value;
 97         }
 98         public override long Read(byte* buflong count)
 99         {
100             if (count < 0)
101             {
102                 ThrowInvalidParameterException();
103             }
104             Flush();
105             if (bytesAvailable == 0)
106             {
107                 FillBuf();
108             }
109             long bytesRead = 0;
110             long n = Min(bytesAvailablecount);
111             for (long i = 0; i < n; ++i;)
112             {
113                 buf[i] = buffer[pos++];
114                 ++bytesRead;
115                 --bytesAvailable;
116             }
117             return bytesRead;
118         }
119         public override void Write(byte x)
120         {
121             if (end >= buffer.Size())
122             {
123                 Flush();
124             }
125             buffer[end++] = x;
126         }
127         public override void Write(byte* buflong count)
128         {
129             if (count < 0)
130             {
131                 ThrowInvalidParameterException();
132             }
133             for (long i = 0; i < count; ++i;)
134             {
135                 Write(buf[i]);
136             }
137         }
138         public override void Flush()
139         {
140             if (end != 0)
141             {
142                 baseStream->Write(cast<byte*>(buffer.Mem())end);
143                 baseStream->Flush();
144                 end = 0;
145             }
146         }
147         public override void Seek(long posOrigin origin)
148         {
149             Flush();
150             bytesAvailable = 0;
151             baseStream->Seek(posorigin);
152         }
153         public override long Tell()
154         {
155             Flush();
156             return baseStream->Tell() - bytesAvailable;
157         }
158         public nothrow const SharedPtr<ByteStream>& ContainedStream()
159         {
160             return baseStream;
161         }
162         private void FillBuf()
163         {
164             bytesAvailable = baseStream->Read(cast<byte*>(buffer.Mem())buffer.Size());
165             pos = 0;
166         }
167         private SharedPtr<ByteStream> baseStream;
168         private IOBuffer buffer;
169         private long pos;
170         private long bytesAvailable;
171         private long end;
172     }
173 }