Beispiel #1
0
        // -------------------------------------------------------------------------------------------
        /// <summary>
        /// Gives, in a target byte array, another one readed from a stream, until consume a number of bytes or before some marks.
        /// Return the index of the found mark or -1 if the consumable bytes limit was reached.
        /// For efficiency, this capture is divided in two types...
        /// One simple, applicable to any underlying Stream, for when the marks only have one byte of lenght,
        /// and other complex for when the marks are of greater lenght (in that case the Stream must support Seek).
        /// </summary>
        public static int CaptureStreamReaderSegment(ref byte[] TargetSegment, BinaryReader TorrentReader, int BytesNumberLimit, params byte[][] LimitMarks)
        {
            if (BytesNumberLimit < 1 || LimitMarks.GetLength(0) < 1)
            {
                throw new UsageAnomaly("Limits for stream reading are not well established.", new DataWagon("BytesNumberLimit", BytesNumberLimit)
                                       .Add("LimitMarks", LimitMarks));
            }
            // Note: It could be validated that each LimitMarks item is a byte array and not a null reference,
            //       but that is omitted to avoid performance impact.

            int MarksCount     = LimitMarks.GetLength(0);
            int Ind            = 0;
            int MarksMaxLength = 0;

            // Next, the lenght of the marks are determined
            bool MarksAreShort = true;

            for (Ind = 0; Ind < MarksCount; Ind++)
            {
                if (LimitMarks[Ind].Length > 1)
                {
                    MarksAreShort = false;
                    if (LimitMarks[Ind].Length > MarksMaxLength)
                    {
                        MarksMaxLength = LimitMarks[Ind].Length;
                    }
                }
            }

            if (MarksMaxLength > LimitMarkMaxLength)
            {
                throw new UsageAnomaly("Segment limit marks exceeds the limit established at " + LimitMarkMaxLength.ToString() + ".", MarksMaxLength);
            }

            if (MarksAreShort)    // Simple implementation, applicable to any stream
            {
                return(CaptureSegmentWithSimpleStreamReader(ref TargetSegment, TorrentReader, BytesNumberLimit, LimitMarks));
            }

            // Complex implementetion, only applicable for seek-capable streams.
            if (!TorrentReader.BaseStream.CanSeek)
            {
                throw new UsageAnomaly("A seek capable Stream is required when exists limit marks with more than one byte.", TorrentReader.BaseStream);
            }

            return(CaptureSegmentWithComplexStreamReader(ref TargetSegment, TorrentReader, BytesNumberLimit, MarksMaxLength, LimitMarks));
        }
Beispiel #2
0
        // -------------------------------------------------------------------------------------------
        /// <summary>
        /// Gives, in a target byte array, another one readed from a stream, until consume a number of bytes or before some marks conformed by more than one byte.
        /// Return the index of the found mark or -1 if the consumable bytes limit was reached.
        /// </summary>
        private static int CaptureSegmentWithComplexStreamReader(ref byte[] TargetSegment, BinaryReader TorrentReader, int BytesNumberLimit,
                                                                 int MarksMaxLength, params byte[][] LimitMarks)
        {
            int CaptureEndingCause    = -1;
            int MarksCount            = LimitMarks.GetLength(0);
            SimpleList <byte[]> Parts = new SimpleList <byte[]>();

            byte[] Part = new byte[0];
            int    ConsumedBytesCount = 0;
            int    ConsumedBytesTotal = 0;
            int    FoundedPosition    = 0;
            int    Pos = 0;

            while ((ConsumedBytesCount = (Part = TorrentReader.ReadBytes(BLOCK_SIZE_TINY)).Length) > 0)
            {
                ConsumedBytesTotal += ConsumedBytesCount;
                Pos = -1;
                foreach (byte[] Mark in LimitMarks)
                {
                    Pos++;
                    if ((FoundedPosition = Search(Part, Mark)) >= 0)
                    {
                        CaptureEndingCause = Pos;
                        TorrentReader.BaseStream.Seek((Part.Length - (FoundedPosition + Mark.Length)) * -1, SeekOrigin.Current);
                        Part = ExtractSegment(Part, 0, FoundedPosition);
                        break;
                    }
                }

                if (FoundedPosition >= 0)
                {
                    Parts.Add(Part);
                    break;
                }

                if (ConsumedBytesTotal >= BytesNumberLimit)
                {
                    throw new UsageAnomaly("Stream has been readed/consumed until reach the " + BytesNumberLimit.ToString() + " bytes limit.",
                                           new DataWagon("ConsumedBytesCount", ConsumedBytesCount));
                }

                if (ConsumedBytesCount == BLOCK_SIZE_TINY)
                {
                    Part = ExtractSegment(Part, 0, Part.Length - MarksMaxLength);
                }

                Parts.Add(Part);

                // If less than the expected bytes were read, then means the stream's end was reached.
                if (ConsumedBytesCount < BLOCK_SIZE_TINY)
                {
                    break;
                }

                TorrentReader.BaseStream.Seek(MarksMaxLength * -1, SeekOrigin.Current);
            }

            TargetSegment = new byte[((BLOCK_SIZE_TINY - MarksMaxLength) * (Parts.Count - 1)) + Part.Length];
            Pos           = 0;
            foreach (byte[] Fragment in Parts)
            {
                CopyByteArray(TargetSegment, Fragment, Pos, (byte)0, false);
                Pos += Fragment.Length;
            }

            return(CaptureEndingCause);
        }
Beispiel #3
0
        // -------------------------------------------------------------------------------------------
        /// <summary>
        /// Gives, in a target byte array, another one readed from a stream, until consume a number of bytes or before some marks conformed by only one byte.
        /// Return the index of the found mark or -1 if the consumable bytes limit was reached.
        /// </summary>
        private static int CaptureSegmentWithSimpleStreamReader(ref byte[] TargetSegment, BinaryReader TorrentReader, int BytesNumberLimit,
                                                                params byte[][] LimitMarks)
        {
            int  CaptureEndingCause = -1;
            int  MarksCount         = LimitMarks.GetLength(0);
            int  Ind = 0;
            int  Pos = 0;
            int  ConsumedBytesCount = 0;
            bool FoundedMark        = false;
            byte Atom = 0;
            SimpleList <byte[]> Parts = new SimpleList <byte[]>();

            byte[] Part           = new byte[0];
            int    PartBytesCount = 0;

            Parts.Add(Part);

            try
            {
                while (ConsumedBytesCount < BytesNumberLimit)
                {
                    Atom = TorrentReader.ReadByte();
                    ConsumedBytesCount++;
                    FoundedMark = false;

                    for (Ind = 0; Ind < MarksCount; Ind++)
                    {
                        if (Atom == LimitMarks[Ind][0])
                        {
                            FoundedMark        = true;
                            CaptureEndingCause = Ind;
                            break;
                        }
                    }

                    if (FoundedMark)
                    {
                        break;
                    }

                    if (PartBytesCount == BLOCK_SIZE_TINY)
                    {
                        Part           = new byte[BLOCK_SIZE_TINY];
                        PartBytesCount = 0;
                        Parts.Add(Part);
                    }

                    Part[PartBytesCount] = Atom;
                    PartBytesCount++;
                }

                throw new UsageAnomaly("Stream has been readed/consumed until reach the " + BytesNumberLimit.ToString() + " bytes limit.",
                                       new DataWagon("ConsumedBytesCount", ConsumedBytesCount));
            }
#pragma warning disable 168
            catch (EndOfStreamException Anomaly)
            {   // The possible end of the stream is expected.
            };
#pragma warning restore 168

            TargetSegment = new byte[(BLOCK_SIZE_TINY * (Parts.Count - 1)) + PartBytesCount];
            Ind           = 0;
            Pos           = 0;
            foreach (byte[] Fragment in Parts)
            {
                Ind++;
                CopyByteArray(TargetSegment, (Ind < Parts.Count ? Fragment : BytesHandling.ExtractSegment(Fragment, 0, PartBytesCount)), Pos, (byte)0, false);
                Pos += BLOCK_SIZE_TINY;
            }

            return(CaptureEndingCause);
        }