using System; using System.Collections.Generic; using System.Text; namespace Common { public static class TextProcessing { private static readonly string[] SizeSuffixes = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" }; public static string SizeSuffix(long value, int digitsCount = 3) { if (value < 0) { throw new ArgumentException(@"Bytes should not be negative", nameof(value)); } var magnitude = (int)Math.Max(0, Math.Log(value, 1024)); var adjustedSize = value / Math.Pow(1024, magnitude); string result; if (adjustedSize != 0) { int digits = (int)Math.Log10(Math.Truncate(adjustedSize)) + 1; result = adjustedSize.ToString("N" + Math.Max(digitsCount - digits, 0)); } else result = "0"; return result + " " + SizeSuffixes[magnitude]; } public static IEnumerable SplitAndKeep(this string text, string[] separators) { int start = 0; int index; string lastSeparator = null; while ((index = text.IndexOfAny(separators, start, out string separator)) != -1) { if (start == 0) { yield return text.Substring(0, index); } else { yield return text.Substring(start - lastSeparator?.Length ?? 0, index - start - lastSeparator?.Length ?? 0); } start = index + separator.Length; lastSeparator = separator; } if (start < text.Length) { yield return text.Substring(start - lastSeparator?.Length ?? 0); } } public static int IndexOfAny(this string text, string[] anyOf, int startIndex, out string resultSeparator) { int result = -1; resultSeparator = null; foreach (var separator in anyOf) { int index = text.IndexOf(separator, startIndex, StringComparison.Ordinal); if (index >= startIndex && result < index) { result = index; resultSeparator = separator; } } return result; } public static bool StartsWith(this string text, string value, int start, StringComparison comparisonType) { // TODO: Can be possibly optimized without temporary string creation return text.Substring(start).StartsWith(value, comparisonType); } public static string Repeat(this string s, int n) => new StringBuilder(s.Length * n).Insert(0, s, n).ToString(); } }