// ------------------------------------------------------------------------------------------- /// <summary> /// Returns array of string segments divided by a separator and, /// optionally, omitting empty segments. /// PENDING: Optimize with IndexOfAny for searching with the first character. /// </summary> public static string[] Segment(this string Text, string Separator, bool OmitEmptySegments = false) { if (Text.Length == 0 || Separator.Length == 0) { return(new string[0]); } int SeparatorLength = Separator.Length; int InitialPosition = 0, FinalPosition = 0; SimpleList <string> List = new SimpleList <string>(); string Fragment = ""; while ((FinalPosition = Text.IndexOf(Separator, InitialPosition)) >= 0) { Fragment = Text.Substring(InitialPosition, (FinalPosition - InitialPosition)); if (!OmitEmptySegments || Fragment.Length > 0) { List.Add(Fragment); } InitialPosition = FinalPosition + SeparatorLength; } Fragment = Text.Substring(InitialPosition); if (!OmitEmptySegments || Fragment.Length > 0) { List.Add(Fragment); } return(List.GetArray()); }
// ------------------------------------------------------------------------------------------- /// <summary> /// Returns an array of bytes segments divided by a separator. /// </summary> public static byte[][] Segment(this byte[] TargetBlock, byte[] Separator) { if (TargetBlock.Length == 0 || Separator.Length == 0) { return(new byte[0][]); } int SeparatorLength = Separator.Length; int InitialPosition = 0, FinalPosition = 0; SimpleList <byte[]> SegmentsList = new SimpleList <byte[]>(); while ((FinalPosition = Search(TargetBlock, Separator, InitialPosition)) >= 0) { SegmentsList.Add(ExtractSegment(TargetBlock, InitialPosition, (FinalPosition - InitialPosition))); InitialPosition = FinalPosition + SeparatorLength; } SegmentsList.Add(ExtractSegment(TargetBlock, InitialPosition)); return(SegmentsList.GetArray()); }
// ------------------------------------------------------------------------------------------- /// <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); }
// ------------------------------------------------------------------------------------------- /// <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); }