/// <summary>Evaluates a terminfo formatting string, using the supplied argument.</summary> /// <param name="format">The format string.</param> /// <param name="arg">The argument to the format string.</param> /// <returns>The formatted string.</returns> public static string Evaluate(string format, FormatParam arg) { FormatParam[] args = t_cachedOneElementArgsArray ??= new FormatParam[1]; args[0] = arg; return(Evaluate(format, args)); }
/// <summary>Evaluates a terminfo formatting string, using the supplied arguments.</summary> /// <param name="format">The format string.</param> /// <param name="arg1">The first argument to the format string.</param> /// <param name="arg2">The second argument to the format string.</param> /// <returns>The formatted string.</returns> public static string Evaluate(string format, FormatParam arg1, FormatParam arg2) { FormatParam[] args = t_cachedTwoElementArgsArray ??= new FormatParam[2]; args[0] = arg1; args[1] = arg2; return(Evaluate(format, args)); }
/// <summary>Evaluates a terminfo formatting string, using the supplied argument.</summary> /// <param name="format">The format string.</param> /// <param name="arg">The argument to the format string.</param> /// <returns>The formatted string.</returns> public static string Evaluate(string format, FormatParam arg) { FormatParam[]? args = t_cachedOneElementArgsArray; if (args == null) { t_cachedOneElementArgsArray = args = new FormatParam[1]; } args[0] = arg; return(Evaluate(format, args)); }
/// <summary>Evaluates a terminfo formatting string, using the supplied arguments.</summary> /// <param name="format">The format string.</param> /// <param name="arg1">The first argument to the format string.</param> /// <param name="arg2">The second argument to the format string.</param> /// <returns>The formatted string.</returns> public static string Evaluate(string format, FormatParam arg1, FormatParam arg2) { FormatParam[]? args = t_cachedTwoElementArgsArray; if (args == null) { t_cachedTwoElementArgsArray = args = new FormatParam[2]; } args[0] = arg1; args[1] = arg2; return(Evaluate(format, args)); }
/// <summary>Gets the lazily-initialized dynamic or static variables collection, based on the supplied variable name.</summary> /// <param name="c">The name of the variable.</param> /// <param name="dynamicVars">The lazily-initialized dynamic variables collection.</param> /// <param name="staticVars">The lazily-initialized static variables collection.</param> /// <param name="index">The index to use to index into the variables.</param> /// <returns>The variables collection.</returns> private static FormatParam[] GetDynamicOrStaticVariables( char c, ref FormatParam[] dynamicVars, ref FormatParam[] staticVars, out int index) { if (c >= 'A' && c <= 'Z') { index = c - 'A'; return(staticVars ?? (staticVars = new FormatParam[26])); // one slot for each letter of alphabet } else if (c >= 'a' && c <= 'z') { index = c - 'a'; return(dynamicVars ?? (dynamicVars = new FormatParam[26])); // one slot for each letter of alphabet } else { throw new InvalidOperationException(SR.IO_TermInfoInvalid); } }
/// <summary>Gets the lazily-initialized dynamic or static variables collection, based on the supplied variable name.</summary> /// <param name="c">The name of the variable.</param> /// <param name="dynamicVars">The lazily-initialized dynamic variables collection.</param> /// <param name="staticVars">The lazily-initialized static variables collection.</param> /// <param name="index">The index to use to index into the variables.</param> /// <returns>The variables collection.</returns> private static FormatParam[] GetDynamicOrStaticVariables( char c, ref FormatParam[]?dynamicVars, ref FormatParam[]?staticVars, out int index) { if (char.IsAsciiLetterUpper(c)) { index = c - 'A'; return(staticVars ?? (staticVars = new FormatParam[26])); // one slot for each letter of alphabet } else if (char.IsAsciiLetterLower(c)) { index = c - 'a'; return(dynamicVars ?? (dynamicVars = new FormatParam[26])); // one slot for each letter of alphabet } else { throw new InvalidOperationException(SR.IO_TermInfoInvalid); } }
public void Push(FormatParam item) { if (_arr.Length == _count){ var newArr = new FormatParam[_arr.Length * 2]; Array.Copy(_arr, 0, newArr, 0, _arr.Length); _arr = newArr; } _arr[_count++] = item; }
/// <summary>Gets the lazily-initialized dynamic or static variables collection, based on the supplied variable name.</summary> /// <param name="c">The name of the variable.</param> /// <param name="dynamicVars">The lazily-initialized dynamic variables collection.</param> /// <param name="staticVars">The lazily-initialized static variables collection.</param> /// <param name="index">The index to use to index into the variables.</param> /// <returns>The variables collection.</returns> private static FormatParam[] GetDynamicOrStaticVariables( char c, ref FormatParam[] dynamicVars, ref FormatParam[] staticVars, out int index) { if (c >= 'A' && c <= 'Z'){ index = c - 'A'; return staticVars ?? (staticVars = new FormatParam[26]); // one slot for each letter of alphabet } else if (c >= 'a' && c <= 'z') { index = c - 'a'; return dynamicVars ?? (dynamicVars = new FormatParam[26]); // one slot for each letter of alphabet } else throw new InvalidOperationException("Terminfo database contains invalid values"); }
/// <summary>Evaluates a terminfo formatting string, using the supplied arguments and processing data structures.</summary> /// <param name="format">The format string.</param> /// <param name="pos">The position in <paramref name="format"/> to start processing.</param> /// <param name="args">The arguments to the format string.</param> /// <param name="stack">The stack to use as the format string is evaluated.</param> /// <param name="dynamicVars">A lazily-initialized collection of variables.</param> /// <param name="staticVars">A lazily-initialized collection of variables.</param> /// <returns> /// The formatted string; this may be empty if the evaluation didn't yield any output. /// The evaluation stack will have a 1 at the top if all processing was completed at invoked level /// of recursion, and a 0 at the top if we're still inside of a conditional that requires more processing. /// </returns> private static string EvaluateInternal( string format, ref int pos, FormatParam[] args, LowLevelStack stack, ref FormatParam[] dynamicVars, ref FormatParam[] staticVars) { // Create a StringBuilder to store the output of this processing. We use the format's length as an // approximation of an upper-bound for how large the output will be, though with parameter processing, // this is just an estimate, sometimes way over, sometimes under. StringBuilder output = new StringBuilder(format.Length); // Format strings support conditionals, including the equivalent of "if ... then ..." and // "if ... then ... else ...", as well as "if ... then ... else ... then ..." // and so on, where an else clause can not only be evaluated for string output but also // as a conditional used to determine whether to evaluate a subsequent then clause. // We use recursion to process these subsequent parts, and we track whether we're processing // at the same level of the initial if clause (or whether we're nested). bool sawIfConditional = false; // Process each character in the format string, starting from the position passed in. for (; pos < format.Length; pos++){ // '%' is the escape character for a special sequence to be evaluated. // Anything else just gets pushed to output. if (format[pos] != '%') { output.Append(format[pos]); continue; } // We have a special parameter sequence to process. Now we need // to look at what comes after the '%'. ++pos; switch (format[pos]) { // Output appending operations case '%': // Output the escaped '%' output.Append('%'); break; case 'c': // Pop the stack and output it as a char output.Append((char)stack.Pop().Int32); break; case 's': // Pop the stack and output it as a string output.Append(stack.Pop().String); break; case 'd': // Pop the stack and output it as an integer output.Append(stack.Pop().Int32); break; case 'o': case 'X': case 'x': case ':': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': // printf strings of the format "%[[:]flags][width[.precision]][doxXs]" are allowed // (with a ':' used in front of flags to help differentiate from binary operations, as flags can // include '-' and '+'). While above we've special-cased common usage (e.g. %d, %s), // for more complicated expressions we delegate to printf. int printfEnd = pos; for (; printfEnd < format.Length; printfEnd++) // find the end of the printf format string { char ec = format[printfEnd]; if (ec == 'd' || ec == 'o' || ec == 'x' || ec == 'X' || ec == 's') { break; } } if (printfEnd >= format.Length) throw new InvalidOperationException("Terminfo database contains invalid values"); string printfFormat = format.Substring(pos - 1, printfEnd - pos + 2); // extract the format string if (printfFormat.Length > 1 && printfFormat[1] == ':') printfFormat = printfFormat.Remove(1, 1); output.Append(FormatPrintF(printfFormat, stack.Pop().Object)); // do the printf formatting and append its output break; // Stack pushing operations case 'p': // Push the specified parameter (1-based) onto the stack pos++; stack.Push(args[format[pos] - '1']); break; case 'l': // Pop a string and push its length stack.Push(stack.Pop().String.Length); break; case '{': // Push integer literal, enclosed between braces pos++; int intLit = 0; while (format[pos] != '}') { intLit = (intLit * 10) + (format[pos] - '0'); pos++; } stack.Push(intLit); break; case '\'': // Push literal character, enclosed between single quotes stack.Push((int)format[pos + 1]); pos += 2; break; // Storing and retrieving "static" and "dynamic" variables case 'P': // Pop a value and store it into either static or dynamic variables based on whether the a-z variable is capitalized pos++; int setIndex; FormatParam[] targetVars = GetDynamicOrStaticVariables(format[pos], ref dynamicVars, ref staticVars, out setIndex); targetVars[setIndex] = stack.Pop(); break; case 'g': // Push a static or dynamic variable; which is based on whether the a-z variable is capitalized pos++; int getIndex; FormatParam[] sourceVars = GetDynamicOrStaticVariables(format[pos], ref dynamicVars, ref staticVars, out getIndex); stack.Push(sourceVars[getIndex]); break; // Binary operations case '+': case '-': case '*': case '/': case 'm': case '^': // arithmetic case '&': case '|': // bitwise case '=': case '>': case '<': // comparison case 'A': case 'O': // logical int second = stack.Pop().Int32; // it's a stack... the second value was pushed last int first = stack.Pop().Int32; int res; switch (format[pos]) { case '+': res = first + second; break; case '-': res = first - second; break; case '*': res = first * second; break; case '/': res = first / second; break; case 'm': res = first % second; break; case '^': res = first ^ second; break; case '&': res = first & second; break; case '|': res = first | second; break; case '=': res = AsInt(first == second); break; case '>': res = AsInt(first > second); break; case '<': res = AsInt(first < second); break; case 'A': res = AsInt(AsBool(first) && AsBool(second)); break; case 'O': res = AsInt(AsBool(first) || AsBool(second)); break; default: res = 0; break; } stack.Push(res); break; // Unary operations case '!': case '~': int value = stack.Pop().Int32; stack.Push( format[pos] == '!' ? AsInt(!AsBool(value)) : ~value); break; // Augment first two parameters by 1 case 'i': args[0] = 1 + args[0].Int32; args[1] = 1 + args[1].Int32; break; // Conditional of the form %? if-part %t then-part %e else-part %; // The "%e else-part" is optional. case '?': sawIfConditional = true; break; case 't': // We hit the end of the if-part and are about to start the then-part. // The if-part left its result on the stack; pop and evaluate. bool conditionalResult = AsBool(stack.Pop().Int32); // Regardless of whether it's true, run the then-part to get past it. // If the conditional was true, output the then results. pos++; string thenResult = EvaluateInternal(format, ref pos, args, stack, ref dynamicVars, ref staticVars); if (conditionalResult) { output.Append(thenResult); } // We're past the then; the top of the stack should now be a Boolean // indicating whether this conditional has more to be processed (an else clause). if (!AsBool(stack.Pop().Int32)) { // Process the else clause, and if the conditional was false, output the else results. pos++; string elseResult = EvaluateInternal(format, ref pos, args, stack, ref dynamicVars, ref staticVars); if (!conditionalResult) { output.Append(elseResult); } // Now we should be done (any subsequent elseif logic will have bene handled in the recursive call). if (!AsBool(stack.Pop().Int32)) { throw new InvalidOperationException("Terminfo database contains invalid values"); } } // If we're in a nested processing, return to our parent. if (!sawIfConditional) { stack.Push(1); return output.ToString(); } // Otherwise, we're done processing the conditional in its entirety. sawIfConditional = false; break; case 'e': case ';': // Let our caller know why we're exiting, whether due to the end of the conditional or an else branch. stack.Push(AsInt(format[pos] == ';')); return output.ToString(); // Anything else is an error default: throw new InvalidOperationException("Terminfo database contains invalid values"); } } stack.Push(1); return output.ToString(); }
public FormatParam Pop() => default; // 0x000000018067F0C0-0x000000018067F180 public void Push(FormatParam item) { } // 0x000000018067F180-0x000000018067F290
/// <summary>Evaluates a terminfo formatting string, using the supplied arguments.</summary> /// <param name="format">The format string.</param> /// <param name="arg1">The first argument to the format string.</param> /// <param name="arg2">The second argument to the format string.</param> /// <returns>The formatted string.</returns> public static string Evaluate(string format, FormatParam arg1, FormatParam arg2) { FormatParam[] args = t_cachedTwoElementArgsArray; if (args == null) { t_cachedTwoElementArgsArray = args = new FormatParam[2]; } args[0] = arg1; args[1] = arg2; return Evaluate(format, args); }
/// <summary>Evaluates a terminfo formatting string, using the supplied argument.</summary> /// <param name="format">The format string.</param> /// <param name="arg">The argument to the format string.</param> /// <returns>The formatted string.</returns> public static string Evaluate(string format, FormatParam arg) { FormatParam[] args = t_cachedOneElementArgsArray; if (args == null) { t_cachedOneElementArgsArray = args = new FormatParam[1]; } args[0] = arg; return Evaluate(format, args); }