< Summary

Class:GDX.IO.CoalesceStream
Assembly:GDX
File(s):D:/BuildAgent/work/GDX-Documentation/Projects/GDX_Development/Packages/com.dotbunny.gdx/GDX/IO/CoalesceStream.cs
Covered lines:0
Uncovered lines:122
Coverable lines:122
Total lines:197
Line coverage:0% (0 of 122)
Covered branches:0
Total branches:0
Covered methods:0
Total methods:21
Method coverage:0% (0 of 21)

Coverage History

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
CoalesceStream()0%2100%
CoalesceStream(...)0%2100%
CoalesceStream(...)0%6200%
CoalesceStream(...)0%6200%
Flush()0%2100%
Read(...)0%42600%
Seek(...)0%20400%
SetLength(...)0%2100%
Write(...)0%6200%
ReadByte()0%6200%
WriteByte(...)0%2100%
EnsureCapacity(...)0%6200%

File(s)

D:/BuildAgent/work/GDX-Documentation/Projects/GDX_Development/Packages/com.dotbunny.gdx/GDX/IO/CoalesceStream.cs

#LineLine coverage
 1// Copyright (c) 2020-2022 dotBunny Inc.
 2// dotBunny licenses this file to you under the BSL-1.0 license.
 3// See the LICENSE file in the project root for more information.
 4
 5using System;
 6using System.Collections.Generic;
 7using System.IO;
 8
 9namespace GDX.IO
 10{
 11    public class CoalesceStream : Stream
 12    {
 013        readonly List<byte[]> m_Blocks = new List<byte[]>();
 14        const long k_BlockSize = 65536;
 15        long m_LengthInternal;
 16
 017        public CoalesceStream()
 018        {
 019            Position = 0;
 020        }
 21
 022        public CoalesceStream(byte[] source)
 023        {
 024            Write(source, 0, source.Length);
 025            Position = 0;
 026        }
 27
 028        public CoalesceStream(int length)
 029        {
 030            SetLength(length);
 031            Position = length;
 032            while (m_Blocks.Count <= BlockId)
 033            {
 034                m_Blocks.Add(new byte[k_BlockSize]);
 035            }
 036            Position = 0;
 037        }
 38
 039        public CoalesceStream(long length)
 040        {
 041            SetLength(length);
 042            Position = length;
 043            while (m_Blocks.Count <= BlockId)
 044            {
 045                m_Blocks.Add(new byte[k_BlockSize]);
 046            }
 047            Position = 0;
 048        }
 49
 050        public override bool CanRead => true;
 051        public override bool CanSeek => true;
 052        public override bool CanWrite => true;
 053        public override long Length => m_LengthInternal;
 054        public sealed override long Position { get; set; }
 55
 56        byte[] Block
 57        {
 58            get
 059            {
 060                while (m_Blocks.Count <= BlockId)
 061                {
 062                    m_Blocks.Add(new byte[k_BlockSize]);
 063                }
 64
 065                return m_Blocks[(int)BlockId];
 066            }
 67        }
 68
 069        long BlockId => Position / k_BlockSize;
 70
 071        long BlockOffset => Position % k_BlockSize;
 72
 73
 74        public override void Flush()
 075        {
 076        }
 77
 78        public override int Read(byte[] buffer, int offset, int count)
 079        {
 080            long readCount = count;
 81
 082            if (readCount < 0)
 083            {
 084                throw new ArgumentOutOfRangeException(nameof(count), readCount,
 85                    "Number of bytes to copy cannot be negative.");
 86            }
 87
 088            long remaining = m_LengthInternal - Position;
 089            if (readCount > remaining)
 090            {
 091                readCount = remaining;
 092            }
 93
 094            if (buffer == null)
 095            {
 096                throw new ArgumentNullException(nameof(buffer), "Buffer cannot be null.");
 97            }
 98
 099            if (offset < 0)
 0100            {
 0101                throw new ArgumentOutOfRangeException(nameof(offset), offset, "Destination offset cannot be negative.");
 102            }
 103
 0104            int read = 0;
 105            do
 0106            {
 0107                long copySize = Math.Min(readCount, k_BlockSize - BlockOffset);
 0108                Buffer.BlockCopy(Block, (int)BlockOffset, buffer, offset, (int)copySize);
 0109                readCount -= copySize;
 0110                offset += (int)copySize;
 111
 0112                read += (int)copySize;
 0113                Position += copySize;
 0114            } while (readCount > 0);
 115
 0116            return read;
 0117        }
 118
 119        public override long Seek(long offset, SeekOrigin origin)
 0120        {
 0121            switch (origin)
 122            {
 123                case SeekOrigin.Begin:
 0124                    Position = offset;
 0125                    break;
 126
 127                case SeekOrigin.End:
 0128                    Position = Length - offset;
 0129                    break;
 130                case SeekOrigin.Current:
 131                default:
 0132                    Position += offset;
 0133                    break;
 134            }
 135
 0136            return Position;
 0137        }
 138
 139        public sealed override void SetLength(long value)
 0140        {
 0141            m_LengthInternal = value;
 0142        }
 143
 144        public sealed override void Write(byte[] buffer, int offset, int count)
 0145        {
 0146            long initialPosition = Position;
 147            try
 0148            {
 149                do
 0150                {
 0151                    int copySize = Math.Min(count, (int)(k_BlockSize - BlockOffset));
 152
 0153                    EnsureCapacity(Position + copySize);
 154
 0155                    Buffer.BlockCopy(buffer, offset, Block, (int)BlockOffset, copySize);
 0156                    count -= copySize;
 0157                    offset += copySize;
 158
 0159                    Position += copySize;
 0160                } while (count > 0);
 0161            }
 0162            catch (Exception)
 0163            {
 0164                Position = initialPosition;
 0165                throw;
 166            }
 0167        }
 168
 169        public override int ReadByte()
 0170        {
 0171            if (Position >= m_LengthInternal)
 0172            {
 0173                return -1;
 174            }
 175
 0176            byte b = Block[BlockOffset];
 0177            Position++;
 178
 0179            return b;
 0180        }
 181
 182        public override void WriteByte(byte value)
 0183        {
 0184            EnsureCapacity(Position + 1);
 0185            Block[BlockOffset] = value;
 0186            Position++;
 0187        }
 188
 189        void EnsureCapacity(long intendedLength)
 0190        {
 0191            if (intendedLength > m_LengthInternal)
 0192            {
 0193                m_LengthInternal = intendedLength;
 0194            }
 0195        }
 196    }
 197}