private static string FunctionIf(Match m, NamePatternParameters p) { // check if Group2 !isNullOrWhiteSpace // Group3 contains the result if true // Group4 (optional) contains the result if false return(string.IsNullOrWhiteSpace(m.Groups[2].Value) ? m.Groups[4].Value : m.Groups[3].Value); }
private static string FunctionReplace(Match m, NamePatternParameters p) { // parameter: 1: replace, 2: text, 3: find, 4: replace if (string.IsNullOrEmpty(m.Groups[2].Value) || string.IsNullOrEmpty(m.Groups[3].Value)) { return(m.Groups[2].Value); } return(m.Groups[2].Value.Replace(m.Groups[3].Value.Replace(" ", " "), m.Groups[4].Value.Replace(" ", " "))); }
private static string FunctionCustomReplace(Match m, NamePatternParameters p) { // parameter: 1: customreplace, 2: key, 3: return if key not available if (p.CustomReplacings == null || string.IsNullOrEmpty(m.Groups[2].Value) || !p.CustomReplacings.ContainsKey(m.Groups[2].Value)) { return(m.Groups[3].Value); } return(p.CustomReplacings[m.Groups[2].Value]); }
private static string FunctionIndexOf(Match m, NamePatternParameters p) { // parameter: 1: source string, 2: string to find if (string.IsNullOrEmpty(m.Groups[2].Value) || string.IsNullOrEmpty(m.Groups[3].Value)) { return(string.Empty); } int index = m.Groups[2].Value.IndexOf(m.Groups[3].Value); return(index >= 0 ? index.ToString() : string.Empty); }
internal static string ResolveFunction(Match match, NamePatternParameters parameters) { var functionName = match.Groups[1].Value.ToLower(); if (!string.IsNullOrEmpty(functionName) && Functions.TryGetValue(functionName, out var func)) { return(func(match, parameters)); } return(string.Empty); }
private static string FunctionCasing(Match m, NamePatternParameters p) { // parameter: 1: casing, 2: text, 3: U for UPPER, L for lower, T for Title switch (m.Groups[3].Value.ToLower()) { case "u": return(m.Groups[2].Value.ToUpperInvariant()); case "l": return(m.Groups[2].Value.ToLowerInvariant()); case "t": return(System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(m.Groups[2].Value)); } return(ParametersInvalid($"casing expects 'U', 'L' or 'T', given is '{m.Groups[3].Value}'", m.Groups[0].Value, p.DisplayError)); }
private static string FunctionPadRight(Match m, NamePatternParameters p) { // check param number: 1: padright, 2: p1, 3: desired length, 4: padding char var padLen = Convert.ToInt32(m.Groups[3].Value); var padChar = m.Groups[4].Value; if (!string.IsNullOrEmpty(padChar)) { return(m.Groups[2].Value.PadRight(padLen, padChar[0])); } return(ParametersInvalid($"No padding char given.", m.Groups[0].Value, p.DisplayError)); }
private static string FunctionRegExReplace(Match m, NamePatternParameters p) { // parameter: 1: replace, 2: text, 3: regEx pattern, 4: replace try { return(Regex.Replace(UnEscapeSpecialCharacters(m.Groups[2].Value), UnEscapeSpecialCharacters(m.Groups[3].Value), UnEscapeSpecialCharacters(m.Groups[4].Value))); } catch (Exception ex) { return(ParametersInvalid($"The regex \"{m.Groups[3].Value}\" caused the exception: {ex.Message}", m.Groups[0].Value, p.DisplayError)); } }
private static string FunctionIfExpr(Match m, NamePatternParameters p) { // tries to evaluate the expression // possible operators are ==, !=, <, >, =<, => var match = Regex.Match(m.Groups[2].Value, @"\A\s*(\d+(?:\.\d*)?)\s*(==|!=|<|<=|>|>=)\s*(\d+(?:\.\d*)?)\s*\Z"); if (match.Success && double.TryParse(match.Groups[1].Value, out double d1) && double.TryParse(match.Groups[3].Value, out double d2) ) { switch (match.Groups[2].Value) { case "==": return(d1 == d2 ? m.Groups[3].Value : m.Groups[4].Value); case "!=": return(d1 != d2 ? m.Groups[3].Value : m.Groups[4].Value); case "<": return(d1 < d2 ? m.Groups[3].Value : m.Groups[4].Value); case "<=": return(d1 <= d2 ? m.Groups[3].Value : m.Groups[4].Value); case ">": return(d1 > d2 ? m.Groups[3].Value : m.Groups[4].Value); case ">=": return(d1 >= d2 ? m.Groups[3].Value : m.Groups[4].Value); } } else { // compare the values as strings match = Regex.Match(m.Groups[2].Value, @"\A\s*(.*?)\s*(==|!=|<=|<|>=|>)\s*(.*?)\s*\Z"); if (match.Success) { int stringComparingResult = match.Groups[1].Value.CompareTo(match.Groups[3].Value); switch (match.Groups[2].Value) { case "==": return(stringComparingResult == 0 ? m.Groups[3].Value : m.Groups[4].Value); case "!=": return(stringComparingResult != 0 ? m.Groups[3].Value : m.Groups[4].Value); case "<": return(stringComparingResult < 0 ? m.Groups[3].Value : m.Groups[4].Value); case "<=": return(stringComparingResult <= 0 ? m.Groups[3].Value : m.Groups[4].Value); case ">": return(stringComparingResult > 0 ? m.Groups[3].Value : m.Groups[4].Value); case ">=": return(stringComparingResult >= 0 ? m.Groups[3].Value : m.Groups[4].Value); } } } return(ParametersInvalid($"The expression for ifexpr invalid: \"{m.Groups[2].Value}\"", m.Groups[0].Value, p.DisplayError)); }
private static string FormatString(string s, string formatString, Match m, NamePatternParameters p, bool isInteger = false) { if (string.IsNullOrEmpty(formatString)) { return(ParametersInvalid("No Format string given", m.Groups[0].Value, p.DisplayError)); } if (string.IsNullOrEmpty(s)) { return(string.Empty); } return(isInteger ? Convert.ToInt32(s).ToString(formatString) : Convert.ToDouble(s).ToString(formatString)); }
private static string FunctionDiv(Match m, NamePatternParameters p) { // returns an integer after dividing the parsed number // parameter: 1: div, 2: number, 3: divided by double number = double.Parse(m.Groups[2].Value); double div = double.Parse(m.Groups[3].Value); if (div > 0) { return(((int)(number / div)).ToString()); } else { return(ParametersInvalid("Division by 0", m.Groups[0].Value, p.DisplayError)); } }
private static string FunctionFloatDiv(Match m, NamePatternParameters p) { // returns an float after dividing the parsed number // parameter: 1: div, 2: number, 3: divided by 4: format string double dividend = double.Parse(m.Groups[2].Value); double divisor = double.Parse(m.Groups[3].Value); if (divisor > 0) { return(((dividend / divisor)).ToString(m.Groups[4].Value)); } else { return(ParametersInvalid("Division by 0", m.Groups[0].Value, p.DisplayError)); } }
private static string FunctionSubString(Match m, NamePatternParameters p) { // check param number: 1: substring, 2: p1, 3: pos, 4: length if (!int.TryParse(m.Groups[3].Value, out var pos)) { return(m.Groups[2].Value); } var text = m.Groups[2].Value; var textLength = text.Length; if (pos < 0) { pos += textLength; } if (pos < 0) { pos = 0; } if (pos >= textLength) { return(string.Empty); } if (string.IsNullOrEmpty(m.Groups[4].Value)) { return(text.Substring(pos)); } var substringLength = int.TryParse(m.Groups[4].Value, out var v) ? v : 0; if (substringLength < 0) { substringLength += textLength - pos; } if (substringLength <= 0) { return(string.Empty); } if (pos + substringLength > textLength) { substringLength = textLength - pos; } return(text.Substring(pos, substringLength)); }
/// <summary> /// Resolves the naming-pattern functions /// </summary> /// <returns></returns> private static string ResolveFunction(Match m, NamePatternParameters parameters) { // function parameters can be non numeric if numbers are parsed try { if (!parameters.ProcessNumberField && m.Groups[2].Value.Contains("{n}")) { return(m.Groups[0].Value); } return(NamePatternFunctions.ResolveFunction(m, parameters)); } catch (Exception ex) { MessageBoxes.ExceptionMessageBox(ex, $"The syntax of the following pattern function\n{m.Groups[0].Value}\ncannot be processed and will be ignored.", "Naming pattern function error"); } return(string.Empty); }
/// <summary> /// Resolves functions in the pattern. /// A function expression looks like {{#function_name:{xxx}|2|3}}, e.g. {{#substring:{HP}|2|3}} /// </summary> /// <param name="pattern"></param> /// <param name="creature"></param> /// <param name="customReplacings">Dictionary of user defined replacings</param> /// <param name="displayError">If true, a MessageBox with the error will be displayed.</param> /// <param name="processNumberField">If true, the {n} will be processed</param> /// <returns></returns> private static string ResolveFunctions(string pattern, Creature creature, Dictionary <string, string> customReplacings, bool displayError, bool processNumberField) { int nrFunctions = 0; int nrFunctionsAfterResolving = NrFunctions(pattern); // the second and third parameter are optional Regex r = new Regex(@"\{\{ *#(\w+) *: *([^\|\{\}]*?) *(?:\| *([^\|\{\}]*?) *)?(?:\| *([^\|\{\}]*?) *)?\}\}", RegexOptions.IgnoreCase); var parameters = new NamePatternParameters { Creature = creature, CustomReplacings = customReplacings, DisplayError = displayError, ProcessNumberField = processNumberField }; // resolve nested functions while (nrFunctions != nrFunctionsAfterResolving) { nrFunctions = nrFunctionsAfterResolving; pattern = r.Replace(pattern, (m) => ResolveFunction(m, parameters)); nrFunctionsAfterResolving = NrFunctions(pattern); } return(pattern); int NrFunctions(string p) { int nr = 0; foreach (char c in p) { if (c == '#') { nr++; } } return(nr); } }
private static string FunctionExpr(Match m, NamePatternParameters p) { // tries to calculate the result of the expression // possible operators are +, -, *, / var match = Regex.Match(m.Groups[2].Value, @"\A\s*(\d+(?:\.\d*)?)\s*(\+|\-|\*|\/)\s*(\d+(?:\.\d*)?)\s*\Z"); if (match.Success && double.TryParse(match.Groups[1].Value, out var d1) && double.TryParse(match.Groups[3].Value, out var d2) ) { switch (match.Groups[2].Value) { case "+": return((d1 + d2).ToString()); case "-": return((d1 - d2).ToString()); case "*": return((d1 * d2).ToString()); case "/": return(d2 == 0 ? "divByZero" : (d1 / d2).ToString()); } } return(ParametersInvalid($"The expression for expr is invalid: \"{m.Groups[2].Value}\"", m.Groups[0].Value, p.DisplayError)); }
private static string FunctionColor(Match m, NamePatternParameters p) { // parameter 1: region id (0,...,5), 2: if not empty, the color name instead of the numerical id is returned, 3: if not empty, the function will return also a value even if the color region is not used on that species. if (!int.TryParse(m.Groups[2].Value, out int regionId) || regionId < 0 || regionId > 5) { return(ParametersInvalid("color region id has to be a number in the range 0 - 5", m.Groups[0].Value, p.DisplayError)); } if (!p.Creature.Species.EnabledColorRegions[regionId] && string.IsNullOrWhiteSpace(m.Groups[4].Value)) { return(string.Empty); // species does not use this region and user doesn't want it (param 3 is empty) } if (p.Creature.colors == null) { return(string.Empty); // no color info } if (string.IsNullOrWhiteSpace(m.Groups[3].Value)) { return(p.Creature.colors[regionId].ToString()); } return(CreatureColors.CreatureColorName(p.Creature.colors[regionId])); }
private static string FunctionLen(Match m, NamePatternParameters p) { // returns the length of the parameter return(m.Groups[2].Value.Length.ToString()); }
private static string FunctionTime(Match m, NamePatternParameters p) { // parameter: 1: time, 2: format return(DateTime.Now.ToString(m.Groups[2].Value)); }
private static string FunctionFormat(Match m, NamePatternParameters p) { // check param number: 1: format, 2: p1, 3: formatString return(FormatString(m.Groups[2].Value, m.Groups[3].Value, m, p)); }
private static string FunctionFormatInt(Match m, NamePatternParameters p) { return(FormatString(m.Groups[2].Value, m.Groups[3].Value, m, p, true)); }