Пример #1
0
        public static async Task <string> ReadLineAsync(ISharedBufferStream stream, MemoryStream stringBuffer)
        {
            bool cr   = false;
            int  used = 0;
            ArraySegment <byte> segment = await stream.SharedBufferReadAsync(Int32.MaxValue);

            if (segment.Count == 0)
            {
                return(null);
            }
            while (!ReadLine(segment, stringBuffer, ref cr, out used))
            {
                segment = await stream.SharedBufferReadAsync(Int32.MaxValue);

                if (segment.Count == 0)
                {
                    return(null);
                }
            }
            if (used != segment.Count)
            {
                stream.SharedBufferRewind(segment.Count - used);
            }
            return(Encoding.UTF8.GetString(stringBuffer.GetBuffer(), 0, (int)stringBuffer.Length));
        }
        public override async Task <int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
        {
            while (true)
            {
                if (isEnd)
                {
                    return(0);
                }
                // do we need to flush some boundary buffer ?
                if (boundaryFlushLength > 0)
                {
                    int size = Math.Min(boundaryFlushLength, count);
                    if (buffer != null)
                    {
                        Buffer.BlockCopy(boundaryBytes, boundaryFlushPos, buffer, offset, size);
                    }
                    boundaryFlushLength -= size;
                    boundaryFlushPos    += size;
                    return(size);
                }
                // do we need to load a new buffer ?
                if (currentBufferCount == 0)
                {
                    ArraySegment <byte> segment = await stream.SharedBufferReadAsync(count);

                    if (segment.Count == 0)
                    {
                        throw new Exception("Invalid boundary stream");
                    }
                    currentBuffer       = segment.Array;
                    currentBufferOffset = segment.Offset;
                    currentBufferCount  = segment.Count;
                }
                int used;
                // if a boundary match start on the previous buffer, finish the match
                if (boundaryPos > 0)
                {
                    int lastBoundaryPos = boundaryPos;
                    // ok, is was a boundary
                    if (TestBoundary(currentBuffer, currentBufferOffset, currentBufferCount, out used))
                    {
                        isEnd = true;
                        // if we read too much, rewined
                        if (currentBufferCount - used > 0)
                        {
                            stream.SharedBufferRewind(currentBufferCount - used);
                        }
                        return(0);
                    }
                    else
                    {
                        // it was a partial boundary
                        if (boundaryPos > 0)
                        {
                            currentBuffer       = null;
                            currentBufferCount  = 0;
                            currentBufferOffset = 0;
                            continue;
                        }
                        // it was not a boundary
                        else
                        {
                            boundaryFlushLength  = lastBoundaryPos + used;
                            boundaryFlushPos     = 0;
                            boundaryPos          = 0;
                            currentBufferOffset += used;
                            currentBufferCount  -= used;
                            // flush what we can
                            int size = Math.Min(boundaryFlushLength, count);
                            if (buffer != null)
                            {
                                Buffer.BlockCopy(boundaryBytes, boundaryFlushPos, buffer, offset, size);
                            }
                            boundaryFlushLength -= size;
                            boundaryFlushPos    += size;
                            return(size);
                        }
                    }
                }
                // go to the first possible boundary match
                int i       = 0;
                int minSize = Math.Min(count, currentBufferCount);
                while (i < minSize)
                {
                    if (currentBuffer[currentBufferOffset + i] == 0x0d)
                    {
                        // match succeed
                        if (TestBoundary(currentBuffer, currentBufferOffset + i, currentBufferCount - i, out used))
                        {
                            isEnd = true;
                            int overflow = currentBufferCount - (i + used);
                            // if we read too much, rewined
                            if (overflow > 0)
                            {
                                stream.SharedBufferRewind(overflow);
                            }
                            // copy what we found before the boundary
                            if (buffer != null)
                            {
                                Buffer.BlockCopy(currentBuffer, currentBufferOffset, buffer, offset, i);
                            }
                            return(i);
                        }
                        else
                        {
                            // partial boundary match
                            if (boundaryPos > 0)
                            {
                                // return the part before the match
                                if (buffer != null)
                                {
                                    Buffer.BlockCopy(currentBuffer, currentBufferOffset, buffer, offset, i);
                                }
                                currentBufferCount  -= i + used;
                                currentBufferOffset += used;
                                return(i);
                            }
                            // match fails continue search
                            else
                            {
                                i++;
                            }
                        }
                    }
                    else
                    {
                        i++;
                    }
                }
                // ok minSize buffer is clean, return it
                if (i == minSize)
                {
                    if (buffer != null)
                    {
                        Buffer.BlockCopy(currentBuffer, currentBufferOffset, buffer, offset, minSize);
                    }
                    currentBufferOffset += minSize;
                    currentBufferCount  -= minSize;
                    return(minSize);
                }
            }
        }