Skip to content

Commit a8e9e64

Browse files
committed
Optimize reverse lookup in query string parsing
1 parent edff8f0 commit a8e9e64

2 files changed

Lines changed: 19 additions & 14 deletions

File tree

src/JsonApiDotNetCore/Queries/Parsing/QueryExpressionParser.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,11 @@ protected virtual void EatSingleCharacterToken(TokenKind kind)
156156
{
157157
if (!TokenStack.TryPop(out Token? token) || token.Kind != kind)
158158
{
159-
char ch = QueryTokenizer.SingleCharacterToTokenKinds.Single(pair => pair.Value == kind).Key;
159+
if (!QueryTokenizer.TokenKindToSingleCharacterLookup.TryGetValue(kind, out char ch))
160+
{
161+
throw new InvalidOperationException($"Token kind '{kind}' is not a single-character token.");
162+
}
163+
160164
int position = token?.Position ?? GetNextTokenPositionOrEnd();
161165
throw new QueryParseException($"{ch} expected.", position);
162166
}

src/JsonApiDotNetCore/Queries/Parsing/QueryTokenizer.cs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using System.Collections.ObjectModel;
21
using System.Text;
32
using JetBrains.Annotations;
43

@@ -7,18 +6,20 @@ namespace JsonApiDotNetCore.Queries.Parsing;
76
[PublicAPI]
87
public sealed class QueryTokenizer
98
{
10-
public static readonly IReadOnlyDictionary<char, TokenKind> SingleCharacterToTokenKinds = new ReadOnlyDictionary<char, TokenKind>(
11-
new Dictionary<char, TokenKind>
12-
{
13-
['('] = TokenKind.OpenParen,
14-
[')'] = TokenKind.CloseParen,
15-
['['] = TokenKind.OpenBracket,
16-
[']'] = TokenKind.CloseBracket,
17-
['.'] = TokenKind.Period,
18-
[','] = TokenKind.Comma,
19-
[':'] = TokenKind.Colon,
20-
['-'] = TokenKind.Minus
21-
});
9+
public static readonly IReadOnlyDictionary<char, TokenKind> SingleCharacterToTokenKinds = new Dictionary<char, TokenKind>
10+
{
11+
['('] = TokenKind.OpenParen,
12+
[')'] = TokenKind.CloseParen,
13+
['['] = TokenKind.OpenBracket,
14+
[']'] = TokenKind.CloseBracket,
15+
['.'] = TokenKind.Period,
16+
[','] = TokenKind.Comma,
17+
[':'] = TokenKind.Colon,
18+
['-'] = TokenKind.Minus
19+
}.AsReadOnly();
20+
21+
internal static readonly IReadOnlyDictionary<TokenKind, char> TokenKindToSingleCharacterLookup =
22+
SingleCharacterToTokenKinds.ToDictionary(pair => pair.Value, pair => pair.Key).AsReadOnly();
2223

2324
private readonly string _source;
2425
private readonly StringBuilder _textBuffer = new();

0 commit comments

Comments
 (0)