Skip to content

Commit 57980a6

Browse files
stephentoubrzikm
authored andcommitted
Use span-based dictionary lookup in System.Console (dotnet#103742)
* Use span-based dictionary lookup in System.Console * Fix ctor
1 parent ee9205d commit 57980a6

File tree

2 files changed

+11
-20
lines changed

2 files changed

+11
-20
lines changed

src/libraries/System.Console/src/System/IO/KeyParser.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,15 @@ private static bool TryParseTerminalInputSequence(char[] buffer, TerminalFormatS
6262
return false;
6363
}
6464

65-
Dictionary<ReadOnlyMemory<char>, ConsoleKeyInfo> terminfoDb = terminalFormatStrings.KeyFormatToConsoleKey; // the most important source of truth
65+
Dictionary<string, ConsoleKeyInfo>.AlternateLookup<ReadOnlySpan<char>> terminfoDb = // the most important source of truth
66+
terminalFormatStrings.KeyFormatToConsoleKey.GetAlternateLookup<string, ConsoleKeyInfo, ReadOnlySpan<char>>();
6667
ConsoleModifiers modifiers = ConsoleModifiers.None;
6768
ConsoleKey key;
6869

6970
// Is it a three character sequence? (examples: '^[[H' (Home), '^[OP' (F1))
7071
if (input[1] == 'O' || char.IsAsciiLetter(input[2]) || input.Length == MinimalSequenceLength)
7172
{
72-
if (!terminfoDb.TryGetValue(buffer.AsMemory(startIndex, MinimalSequenceLength), out parsed))
73+
if (!terminfoDb.TryGetValue(buffer.AsSpan(startIndex, MinimalSequenceLength), out parsed))
7374
{
7475
// All terminals which use "^[O{letter}" escape sequences don't define conflicting mappings.
7576
// Example: ^[OH either means Home or simply is not used by given terminal.
@@ -103,7 +104,7 @@ private static bool TryParseTerminalInputSequence(char[] buffer, TerminalFormatS
103104
// Is it a four character sequence used by Linux Console or PuTTy configured to emulate it? (examples: '^[[[A' (F1), '^[[[B' (F2))
104105
if (input[1] == '[' && input[2] == '[' && char.IsBetween(input[3], 'A', 'E'))
105106
{
106-
if (!terminfoDb.TryGetValue(buffer.AsMemory(startIndex, 4), out parsed))
107+
if (!terminfoDb.TryGetValue(buffer.AsSpan(startIndex, 4), out parsed))
107108
{
108109
parsed = new ConsoleKeyInfo(default, ConsoleKey.F1 + input[3] - 'A', false, false, false);
109110
}
@@ -128,7 +129,7 @@ private static bool TryParseTerminalInputSequence(char[] buffer, TerminalFormatS
128129
{
129130
// it's a VT Sequence like ^[[11~ or rxvt like ^[[11^
130131
int sequenceLength = SequencePrefixLength + digitCount + 1;
131-
if (!terminfoDb.TryGetValue(buffer.AsMemory(startIndex, sequenceLength), out parsed))
132+
if (!terminfoDb.TryGetValue(buffer.AsSpan(startIndex, sequenceLength), out parsed))
132133
{
133134
key = MapEscapeSequenceNumber(byte.Parse(input.Slice(SequencePrefixLength, digitCount)));
134135
if (key == default)

src/libraries/System.Console/src/System/TerminalFormatStrings.cs

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ internal sealed class TerminalFormatStrings
5151
/// The dictionary of keystring to ConsoleKeyInfo.
5252
/// Only some members of the ConsoleKeyInfo are used; in particular, the actual char is ignored.
5353
/// </summary>
54-
public readonly Dictionary<ReadOnlyMemory<char>, ConsoleKeyInfo> KeyFormatToConsoleKey =
55-
new Dictionary<ReadOnlyMemory<char>, ConsoleKeyInfo>(new ReadOnlyMemoryContentComparer());
54+
public readonly Dictionary<string, ConsoleKeyInfo> KeyFormatToConsoleKey = new(StringComparer.Ordinal);
5655

5756
/// <summary> Max key length </summary>
5857
public readonly int MaxKeyFormatLength;
@@ -164,7 +163,7 @@ public TerminalFormatStrings(TermInfo.Database? db)
164163
MaxKeyFormatLength = int.MinValue;
165164
MinKeyFormatLength = int.MaxValue;
166165

167-
foreach (KeyValuePair<ReadOnlyMemory<char>, ConsoleKeyInfo> entry in KeyFormatToConsoleKey)
166+
foreach (KeyValuePair<string, ConsoleKeyInfo> entry in KeyFormatToConsoleKey)
168167
{
169168
if (entry.Key.Length > MaxKeyFormatLength)
170169
{
@@ -229,8 +228,8 @@ private void AddKey(TermInfo.Database db, TermInfo.WellKnownStrings keyId, Conso
229228

230229
private void AddKey(TermInfo.Database db, TermInfo.WellKnownStrings keyId, ConsoleKey key, bool shift, bool alt, bool control)
231230
{
232-
ReadOnlyMemory<char> keyFormat = db.GetString(keyId).AsMemory();
233-
if (!keyFormat.IsEmpty)
231+
string? keyFormat = db.GetString(keyId);
232+
if (!string.IsNullOrEmpty(keyFormat))
234233
KeyFormatToConsoleKey[keyFormat] = new ConsoleKeyInfo(key == ConsoleKey.Enter ? '\r' : '\0', key, shift, alt, control);
235234
}
236235

@@ -248,17 +247,8 @@ private void AddPrefixKey(TermInfo.Database db, string extendedNamePrefix, Conso
248247

249248
private void AddKey(TermInfo.Database db, string extendedName, ConsoleKey key, bool shift, bool alt, bool control)
250249
{
251-
ReadOnlyMemory<char> keyFormat = db.GetExtendedString(extendedName).AsMemory();
252-
if (!keyFormat.IsEmpty)
250+
string? keyFormat = db.GetExtendedString(extendedName);
251+
if (!string.IsNullOrEmpty(keyFormat))
253252
KeyFormatToConsoleKey[keyFormat] = new ConsoleKeyInfo('\0', key, shift, alt, control);
254253
}
255-
256-
private sealed class ReadOnlyMemoryContentComparer : IEqualityComparer<ReadOnlyMemory<char>>
257-
{
258-
public bool Equals(ReadOnlyMemory<char> x, ReadOnlyMemory<char> y) =>
259-
x.Span.SequenceEqual(y.Span);
260-
261-
public int GetHashCode(ReadOnlyMemory<char> obj) =>
262-
string.GetHashCode(obj.Span);
263-
}
264254
}

0 commit comments

Comments
 (0)