Skip to content

Commit 692e4e2

Browse files
author
Sébastien Geiser
committed
Better way to compare strings with casing (smaller memory impact)
1 parent e870e31 commit 692e4e2

File tree

1 file changed

+30
-44
lines changed

1 file changed

+30
-44
lines changed

CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs

Lines changed: 30 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,7 @@ public bool OptionCaseSensitiveEvaluationActive
501501
set
502502
{
503503
optionCaseSensitiveEvaluationActive = value;
504+
StringComparisonForCasing = optionCaseSensitiveEvaluationActive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;
504505
Variables = Variables;
505506
operatorsDictionary = new Dictionary<string, ExpressionOperator>(operatorsDictionary, StringComparerForCasing);
506507
defaultVariables = new Dictionary<string, object>(defaultVariables, StringComparerForCasing);
@@ -510,6 +511,8 @@ public bool OptionCaseSensitiveEvaluationActive
510511
}
511512
}
512513

514+
private StringComparison StringComparisonForCasing { get; set; } = StringComparison.Ordinal;
515+
513516
private StringComparer StringComparerForCasing
514517
{
515518
get
@@ -903,23 +906,21 @@ object ManageJumpStatementsOrExpressionEval(string expression)
903906
{
904907
expression = expression.Trim();
905908

906-
string expressionToTest = OptionCaseSensitiveEvaluationActive ? expression : expression.ToLower();
907-
908-
if (expressionToTest.Equals("break"))
909+
if (expression.Equals("break", StringComparisonForCasing))
909910
{
910911
isBreak = true;
911912
return lastResult;
912913
}
913914

914-
if (expressionToTest.Equals("continue"))
915+
if (expression.Equals("continue", StringComparisonForCasing))
915916
{
916917
isContinue = true;
917918
return lastResult;
918919
}
919920

920-
if(expressionToTest.StartsWith("throw "))
921+
if(expression.StartsWith("throw ", StringComparisonForCasing))
921922
{
922-
throw Evaluate(expressionToTest.Remove(0, 6)) as Exception;
923+
throw Evaluate(expression.Remove(0, 6)) as Exception;
923924
}
924925

925926
expression = returnKeywordRegex.Replace(expression, match =>
@@ -1071,9 +1072,6 @@ void ExecuteBlocksStacks()
10711072
if (blockKeywordsBeginingMatch.Success)
10721073
i++;
10731074

1074-
if (!OptionCaseSensitiveEvaluationActive)
1075-
keyword = keyword.ToLower();
1076-
10771075
Match blockBeginningMatch = blockBeginningRegex.Match(script.Substring(i));
10781076

10791077
string subScript = string.Empty;
@@ -1111,7 +1109,7 @@ void ExecuteBlocksStacks()
11111109
throw new ExpressionEvaluatorSyntaxErrorException($"No instruction after [{keyword}] statement.");
11121110
}
11131111

1114-
if (keyword.Equals("elseif"))
1112+
if (keyword.Equals("elseif", StringComparisonForCasing))
11151113
{
11161114
if (ifBlockEvaluatedState == IfBlockEvaluatedState.NoBlockEvaluated)
11171115
{
@@ -1123,7 +1121,7 @@ void ExecuteBlocksStacks()
11231121
ifBlockEvaluatedState = IfBlockEvaluatedState.ElseIf;
11241122
}
11251123
}
1126-
else if (keyword.Equals("else"))
1124+
else if (keyword.Equals("else", StringComparisonForCasing))
11271125
{
11281126
if (ifBlockEvaluatedState == IfBlockEvaluatedState.NoBlockEvaluated)
11291127
{
@@ -1135,7 +1133,7 @@ void ExecuteBlocksStacks()
11351133
ifBlockEvaluatedState = IfBlockEvaluatedState.NoBlockEvaluated;
11361134
}
11371135
}
1138-
else if (keyword.Equals("catch"))
1136+
else if (keyword.Equals("catch", StringComparisonForCasing))
11391137
{
11401138
if (tryBlockEvaluatedState == TryBlockEvaluatedState.NoBlockEvaluated)
11411139
{
@@ -1147,7 +1145,7 @@ void ExecuteBlocksStacks()
11471145
tryBlockEvaluatedState = TryBlockEvaluatedState.Catch;
11481146
}
11491147
}
1150-
else if (keyword.Equals("finally"))
1148+
else if (keyword.Equals("finally", StringComparisonForCasing))
11511149
{
11521150
if (tryBlockEvaluatedState == TryBlockEvaluatedState.NoBlockEvaluated)
11531151
{
@@ -1163,22 +1161,22 @@ void ExecuteBlocksStacks()
11631161
{
11641162
ExecuteBlocksStacks();
11651163

1166-
if (keyword.Equals("if"))
1164+
if (keyword.Equals("if", StringComparisonForCasing))
11671165
{
11681166
ifElseStatementsList.Add(new List<string>() { keywordAttributes[0], subScript });
11691167
ifBlockEvaluatedState = IfBlockEvaluatedState.If;
11701168
tryBlockEvaluatedState = TryBlockEvaluatedState.NoBlockEvaluated;
11711169
}
1172-
else if(keyword.Equals("try"))
1170+
else if(keyword.Equals("try", StringComparisonForCasing))
11731171
{
11741172
tryStatementsList.Add(new List<string>() { subScript });
11751173
ifBlockEvaluatedState = IfBlockEvaluatedState.NoBlockEvaluated;
11761174
tryBlockEvaluatedState = TryBlockEvaluatedState.Try;
11771175
}
1178-
else if (keyword.Equals("do"))
1176+
else if (keyword.Equals("do", StringComparisonForCasing))
11791177
{
11801178
if ((blockKeywordsBeginingMatch = blockKeywordsBeginningRegex.Match(script.Substring(i))).Success
1181-
&& blockKeywordsBeginingMatch.Groups["keyword"].Value.ManageCasing(OptionCaseSensitiveEvaluationActive).Equals("while"))
1179+
&& blockKeywordsBeginingMatch.Groups["keyword"].Value.Equals("while", StringComparisonForCasing))
11821180
{
11831181
i += blockKeywordsBeginingMatch.Length;
11841182
keywordAttributes = GetExpressionsBetweenParenthesesOrOtherImbricableBrackets(script, ref i, true, ";");
@@ -1218,7 +1216,7 @@ void ExecuteBlocksStacks()
12181216
throw new ExpressionEvaluatorSyntaxErrorException("No [while] keyword afte the [do] keyword and block");
12191217
}
12201218
}
1221-
else if (keyword.Equals("while"))
1219+
else if (keyword.Equals("while", StringComparisonForCasing))
12221220
{
12231221
while (!isReturn && (bool)ManageJumpStatementsOrExpressionEval(keywordAttributes[0]))
12241222
{
@@ -1236,7 +1234,7 @@ void ExecuteBlocksStacks()
12361234
}
12371235
}
12381236
}
1239-
else if (keyword.Equals("for"))
1237+
else if (keyword.Equals("for", StringComparisonForCasing))
12401238
{
12411239
void forAction(int index)
12421240
{
@@ -1260,15 +1258,15 @@ void forAction(int index)
12601258
}
12611259
}
12621260
}
1263-
else if (keyword.Equals("foreach"))
1261+
else if (keyword.Equals("foreach", StringComparisonForCasing))
12641262
{
12651263
Match foreachParenthisEvaluationMatch = foreachParenthisEvaluationRegex.Match(keywordAttributes[0]);
12661264

12671265
if (!foreachParenthisEvaluationMatch.Success)
12681266
{
12691267
throw new ExpressionEvaluatorSyntaxErrorException("wrong foreach syntax");
12701268
}
1271-
else if (!foreachParenthisEvaluationMatch.Groups["in"].Value.ManageCasing(OptionCaseSensitiveEvaluationActive).Equals("in"))
1269+
else if (!foreachParenthisEvaluationMatch.Groups["in"].Value.Equals("in", StringComparisonForCasing))
12721270
{
12731271
throw new ExpressionEvaluatorSyntaxErrorException("no [in] keyword found in foreach");
12741272
}
@@ -2621,10 +2619,10 @@ private MethodInfo GetRealMethod(ref Type type, ref object obj, string func, Bin
26212619
List<object> modifiedArgs = new List<object>(args);
26222620

26232621
if (OptionFluidPrefixingActive
2624-
&& (func.ManageCasing(OptionCaseSensitiveEvaluationActive).StartsWith("Fluid".ManageCasing(OptionCaseSensitiveEvaluationActive))
2625-
|| func.ManageCasing(OptionCaseSensitiveEvaluationActive).StartsWith("Fluent".ManageCasing(OptionCaseSensitiveEvaluationActive))))
2622+
&& (func.StartsWith("Fluid", StringComparisonForCasing)
2623+
|| func.StartsWith("Fluent", StringComparisonForCasing)))
26262624
{
2627-
methodInfo = GetRealMethod(ref type, ref obj, func.ManageCasing(OptionCaseSensitiveEvaluationActive).Substring(func.ManageCasing(OptionCaseSensitiveEvaluationActive).StartsWith("Fluid".ManageCasing(OptionCaseSensitiveEvaluationActive)) ? 5 : 6), flag, modifiedArgs, genericsTypes);
2625+
methodInfo = GetRealMethod(ref type, ref obj, func.Substring(func.StartsWith("Fluid", StringComparisonForCasing) ? 5 : 6), flag, modifiedArgs, genericsTypes);
26282626
if (methodInfo != null)
26292627
{
26302628
if (methodInfo.ReturnType == typeof(void))
@@ -2643,11 +2641,11 @@ private MethodInfo GetRealMethod(ref Type type, ref object obj, string func, Bin
26432641

26442642
if (args.Contains(null))
26452643
{
2646-
methodInfo = type.GetMethod(func.ManageCasing(OptionCaseSensitiveEvaluationActive), flag);
2644+
methodInfo = type.GetMethod(func, flag);
26472645
}
26482646
else
26492647
{
2650-
methodInfo = type.GetMethod(func.ManageCasing(OptionCaseSensitiveEvaluationActive), flag, null, args.ConvertAll(arg => arg.GetType()).ToArray(), null);
2648+
methodInfo = type.GetMethod(func, flag, null, args.ConvertAll(arg => arg.GetType()).ToArray(), null);
26512649
}
26522650

26532651
if (methodInfo != null)
@@ -2657,7 +2655,7 @@ private MethodInfo GetRealMethod(ref Type type, ref object obj, string func, Bin
26572655
else
26582656
{
26592657
List<MethodInfo> methodInfos = type.GetMethods(flag)
2660-
.Where(m => m.Name.ManageCasing(OptionCaseSensitiveEvaluationActive).Equals(func.ManageCasing(OptionCaseSensitiveEvaluationActive)) && m.GetParameters().Length == modifiedArgs.Count)
2658+
.Where(m => m.Name.Equals(func, StringComparisonForCasing) && m.GetParameters().Length == modifiedArgs.Count)
26612659
.ToList();
26622660

26632661
for (int m = 0; m < methodInfos.Count && methodInfo == null; m++)
@@ -2762,7 +2760,7 @@ private BindingFlags DetermineInstanceOrStatic(ref Type objType, ref object obj)
27622760
}
27632761
}
27642762

2765-
string GetScriptBetweenCurlyBrackets(string parentScript, ref int index)
2763+
private string GetScriptBetweenCurlyBrackets(string parentScript, ref int index)
27662764
{
27672765
string s;
27682766
string currentScript = string.Empty;
@@ -2908,11 +2906,11 @@ private bool DefaultFunctions(string name, List<string> args, out object result)
29082906
{
29092907
result = complexFunc(this, args);
29102908
}
2911-
else if (OptionEvaluateFunctionActive && name.ManageCasing(OptionCaseSensitiveEvaluationActive).Equals("Evaluate".ManageCasing(OptionCaseSensitiveEvaluationActive)))
2909+
else if (OptionEvaluateFunctionActive && name.Equals("Evaluate", StringComparisonForCasing))
29122910
{
29132911
result = Evaluate((string)Evaluate(args[0]));
29142912
}
2915-
else if (OptionScriptEvaluateFunctionActive && name.ManageCasing(OptionCaseSensitiveEvaluationActive).Equals("ScriptEvaluate".ManageCasing(OptionCaseSensitiveEvaluationActive)))
2913+
else if (OptionScriptEvaluateFunctionActive && name.Equals("ScriptEvaluate", StringComparisonForCasing))
29162914
{
29172915
result = ScriptEvaluate((string)Evaluate(args[0]));
29182916
}
@@ -2943,14 +2941,14 @@ private Type GetTypeByFriendlyName(string typeName, string genericTypes = "", bo
29432941
if (result == null)
29442942
{
29452943
typeName = Regex.Replace(typeName, primaryTypesRegexPattern,
2946-
(Match match) => primaryTypesDict[match.Value.ManageCasing(OptionCaseSensitiveEvaluationActive)].ToString(), optionCaseSensitiveEvaluationActive ? RegexOptions.None : RegexOptions.IgnoreCase);
2944+
(Match match) => primaryTypesDict[OptionCaseSensitiveEvaluationActive ? match.Value : match.Value.ToLower()].ToString(), optionCaseSensitiveEvaluationActive ? RegexOptions.None : RegexOptions.IgnoreCase);
29472945

29482946
result = Type.GetType(typeName, false, !OptionCaseSensitiveEvaluationActive);
29492947
}
29502948

29512949
if (result == null)
29522950
{
2953-
result = Types.Find(type => type.Name.ManageCasing(OptionCaseSensitiveEvaluationActive).Equals(typeName.ManageCasing(OptionCaseSensitiveEvaluationActive)));
2951+
result = Types.Find(type => type.Name.Equals(typeName, StringComparisonForCasing));
29542952
}
29552953

29562954
for (int a = 0; a < Assemblies.Count && result == null; a++)
@@ -3179,18 +3177,6 @@ public TResult Func16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T1
31793177
#endregion
31803178
}
31813179

3182-
#region Internal extentions methods
3183-
3184-
internal static class StringCaseManagementForExpressionEvaluatorExtension
3185-
{
3186-
public static string ManageCasing(this string text, bool isCaseSensitive)
3187-
{
3188-
return isCaseSensitive ? text : text.ToLower();
3189-
}
3190-
}
3191-
3192-
#endregion
3193-
31943180
#region linked enums
31953181

31963182
public enum OptionOnNoReturnKeywordFoundInScriptAction

0 commit comments

Comments
 (0)