using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using ICD.Common.Properties; using ICD.Common.Utils.Extensions; namespace ICD.Common.Utils { public static class StringUtils { private const ushort ASCII_READABLE_START = 32; private const ushort ASCII_READABLE_END = 126; /// /// Returns the number as a string in the format "\\x00" /// /// /// [PublicAPI] public static string ToHexLiteral(int numeric) { return string.Format("\\x{0:X2}", numeric); } /// /// Returns the character as a string in the format "\\x00" /// /// /// [PublicAPI] public static string ToHexLiteral(char c) { return ToHexLiteral(Convert.ToInt32(c)); } /// /// Returns a string as a string in the format "\\x00\\x00..." /// /// /// [PublicAPI] public static string ToHexLiteral(string input) { string[] strings = input.Select(c => ToHexLiteral(c)).ToArray(); return string.Join("", strings); } /// /// Converts a character in the string format "\\x00" to char. /// /// /// [PublicAPI] public static char FromHexLiteralCharacter(string character) { string hexValue = character.Substring(2); return (char)Convert.ToByte(hexValue, 16); } /// /// Converts a string in the format "\\x00\\x00..." to hex representation. /// /// /// [PublicAPI] public static string FromHexLiteral(string data) { return string.Join("", data.Split(4).Select(s => FromHexLiteralCharacter(s).ToString()).ToArray()); } /// /// Converts the char to a human readable character, otherwise returns a hex string /// in the format "\x00" /// /// /// [PublicAPI] public static string ToMixedReadableHexLiteral(char c) { int numeric = Convert.ToInt32(c); if (numeric >= ASCII_READABLE_START && numeric <= ASCII_READABLE_END) return c.ToString(); return ToHexLiteral(c); } /// /// Converts the input string to a string in the format "\x00\x00" with human /// readable characters where possible e.g. "Hello World!x\0D" /// /// /// [PublicAPI] public static string ToMixedReadableHexLiteral(string input) { string[] strings = input.Select(c => ToMixedReadableHexLiteral(c)).ToArray(); return string.Join("", strings); } /// /// Converts bytes to an ascii string. /// /// /// [PublicAPI] public static string ToString(IEnumerable bytes) { byte[] cast = bytes as byte[] ?? bytes.ToArray(); return Encoding.UTF8.GetString(cast, 0, cast.Length); } /// /// Converts bytes to an ascii string. /// /// /// /// [PublicAPI] public static string ToString(IEnumerable bytes, int length) { byte[] cast = bytes as byte[] ?? bytes.ToArray(); return Encoding.UTF8.GetString(cast, 0, length); } /// /// Converts an ascii string to bytes. /// /// /// [PublicAPI] public static byte[] ToBytes(string input) { return Encoding.UTF8.GetBytes(input); } /// /// Attempts to parse the string as an integer. /// /// /// /// [PublicAPI] public static bool TryParse(string value, out int result) { return TryConvert(Convert.ToInt32, value, out result); } /// /// Attempts to parse the string as an unsigned integer. /// /// /// /// [PublicAPI] public static bool TryParse(string value, out uint result) { return TryConvert(Convert.ToUInt32, value, out result); } /// /// Attempts to parse the string as a float. /// /// /// /// [PublicAPI] public static bool TryParse(string value, out float result) { return TryConvert(Convert.ToSingle, value, out result); } /// /// Attempts to parse the string as a bool. /// /// /// /// [PublicAPI] public static bool TryParse(string value, out bool result) { return TryConvert(Convert.ToBoolean, value, out result); } /// /// Attempts to parse the string via the given conversion function. /// /// /// /// /// private static bool TryConvert(Func convertFunc, string value, out T result) { if (convertFunc == null) throw new ArgumentNullException("convertFunc"); result = default(T); bool retVal = false; try { result = convertFunc(value); retVal = true; } catch (FormatException) { } catch (InvalidCastException) { } return retVal; } /// /// Returns the object.ToString() with spaces before capital letters. /// /// /// public static string NiceName(object obj) { return NiceName(obj.ToString()); } /// /// Inserts spaces before capital letters. /// /// http://stackoverflow.com/questions/4488969/split-a-string-by-capital-letters /// /// /// public static string NiceName(string name) { Regex regex = new Regex(@" (?<=[A-Z])(?=[A-Z][a-z]) | (?<=[^A-Z])(?=[A-Z]) | (?<=[A-Za-z])(?=[^A-Za-z])", RegexOptions.IgnorePatternWhitespace); return regex.Replace(name, " "); } /// /// String.Format({0:######}) is unreliable if the number starts with a 0. /// This method fills an input pattern #### from right to left with characters /// from the number. /// /// /// /// public static string SafeNumericFormat(string phoneFormat, string number) { phoneFormat = Reverse(phoneFormat); number = Reverse(number); StringBuilder builder = new StringBuilder(); int index = 0; foreach (char c in phoneFormat) { if (index >= number.Length) { if (c == '#') break; builder.Append(c); continue; } if (c == '#') { builder.Append(number[index]); index++; } else builder.Append(c); } return Reverse(builder.ToString()).TrimStart(); } /// /// Reverses the string. /// /// /// [PublicAPI] public static string Reverse(string input) { char[] charArray = input.ToCharArray(); Array.Reverse(charArray); return new string(charArray); } /// /// Repeats the char the given number of times. /// /// /// /// public static string Repeat(char input, int count) { return Repeat(input.ToString(), count); } /// /// Repeats the string the given number of times. /// /// /// /// [PublicAPI] public static string Repeat(string input, int count) { return count == 0 ? string.Empty : new StringBuilder().Insert(0, input, count).ToString(); } /// /// Returns each item.ToString() in the format "[item1, item2, item3...]" /// /// /// [PublicAPI] public static string ArrayFormat(IEnumerable items) { if (items == null) throw new ArgumentNullException("items"); return string.Format("[{0}]", string.Join(", ", items.Select(i => i.ToString()).ToArray())); } /// /// Given a sequence of numbers, generates a human readable list of numeric ranges. /// E.g. [1, 2, 3, 5, 6] becomes "[1-3, 5-6]". /// /// /// [PublicAPI] public static string ArrayRangeFormat(IEnumerable items) { if (items == null) throw new ArgumentNullException("items"); string[] ranges = MathUtils.GetRanges(items) .Select(r => r[0] == r[1] ? r[0].ToString() : string.Format("{0}-{1}", r[0], r[1])) .ToArray(); return ArrayFormat(ranges); } /// /// Given a sequence of numbers, generates a human readable list of numeric ranges. /// E.g. [1, 2, 3, 5, 6] becomes "[1-3, 5-6]". /// /// /// [PublicAPI] public static string ArrayRangeFormat(IEnumerable items) { if (items == null) throw new ArgumentNullException("items"); return ArrayRangeFormat(items.Select(i => (int)i)); } /// /// Returns a pair of numbers in the format [a - b] /// /// /// /// [PublicAPI] public static string RangeFormat(object a, object b) { return string.Format("[{0} - {1}]", a, b); } /// /// Capitalizes the first character of the string. /// /// /// [PublicAPI] public static string UppercaseFirst(string input) { if (string.IsNullOrEmpty(input)) return input; return char.ToUpper(input[0]) + input.Substring(1); } /// /// Formats an IPID to "0xFF" /// /// /// public static string ToIpIdString(byte ipid) { return string.Format("0x{0:X2}", ipid); } /// /// Formats "0xFF" to an IPID. /// /// /// public static byte FromIpIdString(string value) { value = value.Replace("0x", ""); return Convert.ToByte(value, 16); } /// /// Removes all whitespace from the string. /// /// /// public static string RemoveWhitespace(string text) { return text == null ? null : new string(text.Where(c => !Char.IsWhiteSpace(c)).ToArray()); } /// /// Returns the password as a series of *s /// /// /// public static string PasswordFormat(string password) { return password == null ? null : Repeat('*', password.Length); } /// /// Pads the given string with quotations for readable type clarity. If the string is null, returns "NULL". /// /// /// public static string ToRepresentation(string value) { return value == null ? "NULL" : string.Format("\"{0}\"", value); } /// /// Returns the items in the format "x, y, and z" /// /// /// public static string SerialComma(IEnumerable items) { if (items == null) throw new ArgumentNullException("items"); string previous = null; StringBuilder builder = new StringBuilder(); foreach (string item in items) { if (previous != null) builder.AppendFormat("{0}, ", previous); previous = item; } if (previous != null) { if (builder.Length > 0) builder.AppendFormat("and {0}", previous); else builder.Append(previous); } return builder.ToString(); } } }