using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; namespace EasyDevCore.Common { /// /// String extension helper /// public static class StringExtensions { /// /// Ins the specified string comparison. /// /// The input. /// One of the enumeration values that specifies how the strings will be compared. /// The arguments. /// public static bool In(this string input, StringComparison comparisionType, params string[] args) { if (input == null) return false; foreach (string value in args) { if (!input.Equals(value)) continue; return true; } return false; } /// /// Determines whether the specified arguments has any. /// /// The input. /// The arguments. /// /// true if the specified arguments has any; otherwise, false. /// public static bool HasAny(this string input, params string[] args) { foreach(var p in args) { if (input.IndexOf(p) > -1) return true; } return false; } /// /// Determines whether the specified comparison has any. /// /// The input. /// The comparison. /// The arguments. /// /// true if the specified comparison has any; otherwise, false. /// public static bool HasAny(this string input, StringComparison comparison, params string[] args) { foreach (var p in args) { if (input.IndexOf(p, comparison) > -1) return true; } return false; } /// /// Determines whether [is unicode string] [the specified input]. /// /// The input. /// /// true if [is unicode string] [the specified input]; otherwise, false. /// public static bool IsUnicode(this string input) { return input.ToCharArray().Any(c => c > 255); } /// /// Removes all leading occurrences of whitespace of input string /// /// The input. /// public static string LTrim(this string input) { return input.TrimStart(new char[] { ' ' }); } /// /// Removes all occurrences of whitespace of the end of the input string /// /// The input. /// public static string RTrim(this string input) { return input.TrimEnd(new char[] { ' ' }); } /// /// Lefts the specified length. /// /// The input. /// The length. /// public static string Left(this string input, int len) => (input == null || input.Length <= len) ? input : input.Substring(0, len); /// /// Rights the specified length. /// /// The input. /// The length. /// public static string Right(this string input, int len) => (input == null || input.Length <= len) ? input : input.Substring(input.Length - len, len); /// /// Replaces with case style. /// /// The text. /// The old value. /// The new value. /// Maximum length of the match. /// public static string ReplaceCaseStyle(this string text, string oldValue, string newValue, int maxMatchLength = 0) { var caseReplacement = TransferCaseStyle(oldValue, newValue); return text.Replace(oldValue, caseReplacement); } /// /// Transfers the case style. /// /// The match. /// The replacement. /// Maximum length of the match. /// public static string TransferCaseStyle(string match, string replacement, int maxMatchLength = 0) { char[] replacementChars = replacement.ToCharArray(); if(maxMatchLength == 0) { maxMatchLength = Math.Min(match.Length, replacement.Length); } for (int i = 0; i < maxMatchLength; i++) { if (char.IsLower(match[i])) replacementChars[i] = char.ToLower(replacementChars[i]); else if (char.IsUpper(match[i])) replacementChars[i] = char.ToUpper(replacementChars[i]); } return new string(replacementChars); } /// /// Regexes the get match values. /// /// The input. /// The patterns. /// (Key = Match Value, Value = Group Name) public static Dictionary RegexGetMatchValues(this string input, string patterns) { Dictionary matchValues = new(); Regex re = new Regex(patterns); var groupNames = re.GetGroupNames().Where(x => !(x[0] >= (byte)'0' && x[0] <= (byte)'9')).ToArray(); var matches = re.Matches(input); foreach (Match m in matches.AsParallel()) { foreach (var gn in groupNames) { var mg = m.Groups[gn]; if (mg.Success) { var value = mg.Value; if (!matchValues.ContainsKey(value)) { matchValues.Add(value, gn); } } } } return matchValues; } /// /// Regexes the group match. /// /// The input. /// The patterns. /// The match handler is Func(Group match, string groupname, string replactedText). public static void RegexGroupMatch(this string input, string patterns, Action matchHandler) { Regex re = new Regex(patterns); var groupNames = re.GetGroupNames().Where(x => !(x[0] >= (byte)'0' && x[0] <= (byte)'9')).ToArray(); var matches = re.Matches(input); foreach (Match m in matches.AsParallel()) { foreach (var gn in groupNames) { var mg = m.Groups[gn]; if (mg.Success) { matchHandler(mg); } } } } /// /// Regexes the group replace. /// /// The input. /// The patterns. /// The match handler is Func(Group match, string groupname, string replactedText). /// public static string RegexGroupReplace(this string input, string patterns, Func matchHandler) { Regex re = new Regex(patterns); var groupNames = re.GetGroupNames().Where(x => !(x[0] >= (byte)'0' && x[0] <= (byte)'9')).ToArray(); return re.Replace(input, (MatchEvaluator)((m) => { foreach (var gn in groupNames) { var mg = m.Groups[gn]; if (mg.Success) { return matchHandler(mg, gn); } } return m.Value; })); } /// /// Substitudes the specified input. /// /// The input. /// The index. /// The length. /// The replaced text. /// public static string Substitude(this string input, int index, int length, string replacedText) { return input.Substring(0, index) + replacedText + (index + length > input.Length ? "" : input.Substring(index + length)); } /// /// Substitudes the specified input. /// /// The input. /// The index. /// The replaced text. /// public static string Substitude(this string input, int index, string replacedText) { return input.Substring(0, index) + replacedText + (index + replacedText.Length > input.Length ? "" : input.Substring(index + replacedText.Length)); } /// /// Splits the string. /// /// The input. /// The seperator. /// The split options. /// if set to true [trim space]. /// public static string[] SplitString(this string input, string seperator, StringSplitOptions splitOptions = StringSplitOptions.RemoveEmptyEntries, bool trimSpace = false) { string[] result = input.Split(new string[] { seperator }, splitOptions); if (trimSpace) { return result.Select(s => s.Trim()).ToArray(); } return result; } /// /// Splits the by comma or semi colon (,;). /// /// The input. /// The split options. /// if set to true [trim space]. /// System.String[]. public static string[] SplitByCommaOrSemiColon(this string input, StringSplitOptions splitOptions = StringSplitOptions.RemoveEmptyEntries, bool trimSpace = false) { string[] result = input.Split( new char[] { ',', ';' }, splitOptions); if (trimSpace) { return result.Select(s => s.Trim()).ToArray(); } return result; } /// /// Splits the comma string. /// /// The input. /// The split options. /// if set to true [trim space]. /// public static string[] SplitCommaString(this string input, StringSplitOptions splitOptions = StringSplitOptions.RemoveEmptyEntries, bool trimSpace = false) { string[] result = input.Split(new char[] { ',' }, splitOptions); if (trimSpace) { return result.Select(s => s.Trim()).ToArray(); } return result; } /// /// Splits the semi colon string. /// /// The input. /// The split options. /// if set to true [trim space]. /// public static string[] SplitSemiColonString(this string input, StringSplitOptions splitOptions = StringSplitOptions.RemoveEmptyEntries, bool trimSpace = false) { string[] result = input.Split(new char[] { ';' }, splitOptions); if (trimSpace) { return result.Select(s => s.Trim()).ToArray(); } return result; } /// /// A case insenstive replace function. /// /// The string to examine. /// The value to replace. /// The new value to be inserted /// A string public static string CaseInsenstiveReplace(this string value, string newValue, string oldValue) { Regex regEx = new Regex(oldValue, RegexOptions.IgnoreCase | RegexOptions.Multiline); return regEx.Replace(value, newValue); } /// /// Removes the new line (\n) and carriage return (\r) symbols. /// /// The string to search. /// If true, adds a space (" ") for each newline and carriage /// return found. /// A string public static string RemoveNewLines(this string value, bool addSpace = false) { string replace = string.Empty; if (addSpace) replace = " "; string pattern = @"[\r|\n]"; Regex regEx = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Multiline); return regEx.Replace(value, replace); } /// /// Reverse a string. /// /// The string to reverse /// A string public static string Reverse(this string value) { if (value.Length <= 1) return value; char[] c = value.ToCharArray(); StringBuilder sb = new StringBuilder(c.Length); for (int i = c.Length - 1; i > -1; i--) sb.Append(c[i]); return sb.ToString(); } /// /// Converts a string to sentence case. /// /// The string to convert. /// A string public static string SentenceCase(this string value) { if (value.Length < 1) return value; // start by converting entire string to lower case var lowerCase = value.ToLower(); // matches the first sentence of a string, as well as subsequent sentences var r = new Regex(@"(^[a-z])|\.\s+(.)", RegexOptions.ExplicitCapture); // MatchEvaluator delegate defines replacement of setence starts to uppercase return r.Replace(lowerCase, s => s.Value.ToUpper()); } /// /// Converts a string to title case. /// /// The string to convert. /// A string. public static string TitleCase(this string value) { if (value.Length < 1) return value; // start by converting entire string to lower case var lowerCase = value.ToLower(); // matches the first sentence of a string, as well as subsequent sentences var r = new Regex(@"\b(\w)", RegexOptions.ExplicitCapture); // MatchEvaluator delegate defines replacement of setence starts to uppercase return r.Replace(lowerCase, s => s.Value.ToUpper()); } /// /// Determines whether the specified input is match. /// /// The input. /// The pattern (regular expression). /// if set to true [ignore case]. /// /// true if the specified input is match; otherwise, false. /// public static bool IsMatch(this string input, string pattern, bool ignoreCase = false) { return Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase); } /// /// string like operator. /// /// The input. /// The pattern. /// if set to true [ignore case]. /// public static bool StringLike(this string input, string pattern, bool ignoreCase = false) { return SQLLike(input, pattern.Replace("?", "_").Replace("*", "%"), ignoreCase); } /// /// SQL like operator. /// /// The input. /// The pattern. /// if set to true [ignore case]. /// public static bool SQLLike(this string input, string pattern, bool ignoreCase) { /* Turn "off" all regular expression related syntax in * the pattern string. */ pattern = Regex.Escape(pattern); /* Replace the LIKE wildcard metacharacters with the * equivalent regular expression metacharacters. */ pattern = pattern.Replace("_", ".").Replace("%", ".*"); /* The previous call to Regex.Escape actually turned off * too many metacharacters, i.e. those which are recognized by * both the regular expression engine and the LIKE * statement ([...] and [^...]). Those metacharacters have * to be manually unescaped here. */ pattern = pattern.Replace(@"\[", "[").Replace(@"\]", "]").Replace(@"\^", "^"); if (ignoreCase) { return Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase); } else { return Regex.IsMatch(input, pattern); } } /// /// SQLs the like pattern. /// /// The input. /// The pattern. /// public static bool SQLLike(this string input, string pattern) { bool isMatch = true, isWildCardOn = false, isCharWildCardOn = false, isCharSetOn = false, isNotCharSetOn = false, endOfPattern = false; int lastWildCard = -1; int patternIndex = 0; List set = new List(); char p = '\0'; for (int i = 0; i < input.Length; i++) { char c = input[i]; endOfPattern = (patternIndex >= pattern.Length); if (!endOfPattern) { p = pattern[patternIndex]; if (!isWildCardOn && p == '%') { lastWildCard = patternIndex; isWildCardOn = true; while (patternIndex < pattern.Length && pattern[patternIndex] == '%') { patternIndex++; } if (patternIndex >= pattern.Length) p = '\0'; else p = pattern[patternIndex]; } else if (p == '_') { isCharWildCardOn = true; patternIndex++; } else if (p == '[') { if (pattern[++patternIndex] == '^') { isNotCharSetOn = true; patternIndex++; } else isCharSetOn = true; set.Clear(); if (pattern[patternIndex + 1] == '-' && pattern[patternIndex + 3] == ']') { char start = char.ToUpper(pattern[patternIndex]); patternIndex += 2; char end = char.ToUpper(pattern[patternIndex]); if (start <= end) { for (char ci = start; ci <= end; ci++) { set.Add(ci); } } patternIndex++; } while (patternIndex < pattern.Length && pattern[patternIndex] != ']') { set.Add(pattern[patternIndex]); patternIndex++; } patternIndex++; } } if (isWildCardOn) { if (char.ToUpper(c) == char.ToUpper(p)) { isWildCardOn = false; patternIndex++; } } else if (isCharWildCardOn) { isCharWildCardOn = false; } else if (isCharSetOn || isNotCharSetOn) { bool charMatch = (set.Contains(char.ToUpper(c))); if ((isNotCharSetOn && charMatch) || (isCharSetOn && !charMatch)) { if (lastWildCard >= 0) patternIndex = lastWildCard; else { isMatch = false; break; } } isNotCharSetOn = isCharSetOn = false; } else { if (char.ToUpper(c) == char.ToUpper(p)) { patternIndex++; } else { if (lastWildCard >= 0) patternIndex = lastWildCard; else { isMatch = false; break; } } } } endOfPattern = (patternIndex >= pattern.Length); if (isMatch && !endOfPattern) { bool isOnlyWildCards = true; for (int i = patternIndex; i < pattern.Length; i++) { if (pattern[i] != '%') { isOnlyWildCards = false; break; } } if (isOnlyWildCards) endOfPattern = true; } return isMatch && endOfPattern; } } }