{
/// <summary>Creates an encoding from the current environment.</summary>
/// <returns>The encoding, or null if it could not be determined.</returns>
- internal static Encoding GetEncodingFromCharset()
+ internal static Encoding? GetEncodingFromCharset()
{
- string charset = GetCharset();
+ string? charset = GetCharset();
if (charset != null)
{
try { return Encoding.GetEncoding(charset); }
/// <summary>Gets the current charset name from the environment.</summary>
/// <returns>The charset name if found; otherwise, null.</returns>
- private static string GetCharset()
+ private static string? GetCharset()
{
// Find the first of the locale environment variables that's set.
- string locale = null;
+ string? locale = null;
foreach (string envVar in s_localeEnvVars)
{
locale = Environment.GetEnvironmentVariable(envVar);
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+#nullable enable
using System;
using System.Text;
using System.Collections.Generic;
internal sealed class OSEncoding : Encoding
{
private readonly int _codePage;
- private string _encodingName;
+ private string? _encodingName;
internal OSEncoding(int codePage) : base(codePage)
{
/// </summary>
internal readonly struct StringOrCharArray : IEquatable<StringOrCharArray>
{
- public readonly string String;
+ public readonly string? String;
- public readonly char[] CharArray;
+ public readonly char[]? CharArray;
public readonly int CharArrayOffset;
public readonly int CharArrayCount;
}
}
- public override bool Equals(object obj)
+ public override bool Equals(object? obj)
{
return
obj is StringOrCharArray &&
{
return StringComparer.Ordinal.Equals(this.String, other.String);
}
+ Debug.Assert(other.CharArray != null);
// String vs CharArray
if (this.String.Length != other.CharArrayCount)
return true;
}
+ Debug.Assert(CharArray != null);
// CharArray vs CharArray
if (other.CharArray != null)
return true;
}
+ Debug.Assert(other.String != null);
// CharArray vs String
if (this.CharArrayCount != other.String.Length)
public static int WindowLeft { get { throw null; } set { } }
public static int WindowTop { get { throw null; } set { } }
public static int WindowWidth { get { throw null; } set { } }
- public static event System.ConsoleCancelEventHandler CancelKeyPress { add { } remove { } }
+ public static event System.ConsoleCancelEventHandler? CancelKeyPress { add { } remove { } }
public static void Beep() { }
public static void Beep(int frequency, int duration) { }
public static void Clear() { }
public static int Read() { throw null; }
public static System.ConsoleKeyInfo ReadKey() { throw null; }
public static System.ConsoleKeyInfo ReadKey(bool intercept) { throw null; }
- public static string ReadLine() { throw null; }
+ public static string? ReadLine() { throw null; }
public static void ResetColor() { }
public static void SetBufferSize(int width, int height) { }
public static void SetCursorPosition(int left, int top) { }
public static void SetWindowSize(int width, int height) { }
public static void Write(bool value) { }
public static void Write(char value) { }
- public static void Write(char[] buffer) { }
+ public static void Write(char[]? buffer) { }
public static void Write(char[] buffer, int index, int count) { }
public static void Write(decimal value) { }
public static void Write(double value) { }
public static void Write(int value) { }
public static void Write(long value) { }
- public static void Write(object value) { }
+ public static void Write(object? value) { }
public static void Write(float value) { }
- public static void Write(string value) { }
- public static void Write(string format, object arg0) { }
- public static void Write(string format, object arg0, object arg1) { }
- public static void Write(string format, object arg0, object arg1, object arg2) { }
- public static void Write(string format, params object[] arg) { }
+ public static void Write(string? value) { }
+ public static void Write(string format, object? arg0) { }
+ public static void Write(string format, object? arg0, object? arg1) { }
+ public static void Write(string format, object? arg0, object? arg1, object? arg2) { }
+ public static void Write(string format, params object?[]? arg) { }
[System.CLSCompliantAttribute(false)]
public static void Write(uint value) { }
[System.CLSCompliantAttribute(false)]
public static void WriteLine() { }
public static void WriteLine(bool value) { }
public static void WriteLine(char value) { }
- public static void WriteLine(char[] buffer) { }
+ public static void WriteLine(char[]? buffer) { }
public static void WriteLine(char[] buffer, int index, int count) { }
public static void WriteLine(decimal value) { }
public static void WriteLine(double value) { }
public static void WriteLine(int value) { }
public static void WriteLine(long value) { }
- public static void WriteLine(object value) { }
+ public static void WriteLine(object? value) { }
public static void WriteLine(float value) { }
- public static void WriteLine(string value) { }
- public static void WriteLine(string format, object arg0) { }
- public static void WriteLine(string format, object arg0, object arg1) { }
- public static void WriteLine(string format, object arg0, object arg1, object arg2) { }
- public static void WriteLine(string format, params object[] arg) { }
+ public static void WriteLine(string? value) { }
+ public static void WriteLine(string format, object? arg0) { }
+ public static void WriteLine(string format, object? arg0, object? arg1) { }
+ public static void WriteLine(string format, object? arg0, object? arg1, object? arg2) { }
+ public static void WriteLine(string format, params object?[]? arg) { }
[System.CLSCompliantAttribute(false)]
public static void WriteLine(uint value) { }
[System.CLSCompliantAttribute(false)]
public bool Cancel { get { throw null; } set { } }
public System.ConsoleSpecialKey SpecialKey { get { throw null; } }
}
- public delegate void ConsoleCancelEventHandler(object sender, System.ConsoleCancelEventArgs e);
+ public delegate void ConsoleCancelEventHandler(object? sender, System.ConsoleCancelEventArgs e);
public enum ConsoleColor
{
Black = 0,
public char KeyChar { get { throw null; } }
public System.ConsoleModifiers Modifiers { get { throw null; } }
public bool Equals(System.ConsoleKeyInfo obj) { throw null; }
- public override bool Equals(object value) { throw null; }
+ public override bool Equals(object? value) { throw null; }
public override int GetHashCode() { throw null; }
public static bool operator ==(System.ConsoleKeyInfo a, System.ConsoleKeyInfo b) { throw null; }
public static bool operator !=(System.ConsoleKeyInfo a, System.ConsoleKeyInfo b) { throw null; }
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configurations>netcoreapp-Debug;netcoreapp-Release;uap-Debug;uap-Release</Configurations>
+ <Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Compile Include="System.Console.cs" />
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<RootNamespace>System.Console</RootNamespace>
<AssemblyName>System.Console</AssemblyName>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Configurations>netcoreapp-Unix-Debug;netcoreapp-Unix-Release;netcoreapp-Windows_NT-Debug;netcoreapp-Windows_NT-Release;uap-Windows_NT-Debug;uap-Windows_NT-Release</Configurations>
+ <Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Compile Include="FxCopBaseline.cs" />
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
private const int WriteBufferSize = 256;
private static object InternalSyncObject = new object(); // for synchronizing changing of Console's static fields
- private static TextReader s_in;
- private static TextWriter s_out, s_error;
- private static Encoding s_inputEncoding;
- private static Encoding s_outputEncoding;
+ private static TextReader? s_in;
+ private static TextWriter? s_out, s_error;
+ private static Encoding? s_inputEncoding;
+ private static Encoding? s_outputEncoding;
private static bool s_isOutTextWriterRedirected = false;
private static bool s_isErrorTextWriterRedirected = false;
- private static ConsoleCancelEventHandler s_cancelCallbacks;
- private static ConsolePal.ControlCHandlerRegistrar s_registrar;
+ private static ConsoleCancelEventHandler? s_cancelCallbacks;
+ private static ConsolePal.ControlCHandlerRegistrar? s_registrar;
- internal static T EnsureInitialized<T>(ref T field, Func<T> initializer) where T : class =>
+ internal static T EnsureInitialized<T>([NotNull] ref T? field, Func<T> initializer) where T : class =>
LazyInitializer.EnsureInitialized(ref field, ref InternalSyncObject, initializer);
public static TextReader In => EnsureInitialized(ref s_in, () => ConsolePal.GetOrCreateReader());
// s_out reinitialize the console code page.
if (Volatile.Read(ref s_out) != null && !s_isOutTextWriterRedirected)
{
- s_out.Flush();
+ s_out!.Flush();
Volatile.Write(ref s_out, null);
}
if (Volatile.Read(ref s_error) != null && !s_isErrorTextWriterRedirected)
{
- s_error.Flush();
+ s_error!.Flush();
Volatile.Write(ref s_error, null);
}
});
}
- private static StrongBox<bool> _isStdInRedirected;
- private static StrongBox<bool> _isStdOutRedirected;
- private static StrongBox<bool> _isStdErrRedirected;
+ private static StrongBox<bool>? _isStdInRedirected;
+ private static StrongBox<bool>? _isStdOutRedirected;
+ private static StrongBox<bool>? _isStdErrRedirected;
public static bool IsInputRedirected
{
ConsolePal.SetCursorPosition(left, top);
}
- public static event ConsoleCancelEventHandler CancelKeyPress
+ public static event ConsoleCancelEventHandler? CancelKeyPress
{
add
{
}
[MethodImplAttribute(MethodImplOptions.NoInlining)]
- public static string ReadLine()
+ public static string? ReadLine()
{
return In.ReadLine();
}
}
[MethodImplAttribute(MethodImplOptions.NoInlining)]
- public static void WriteLine(char[] buffer)
+ public static void WriteLine(char[]? buffer)
{
Out.WriteLine(buffer);
}
}
[MethodImplAttribute(MethodImplOptions.NoInlining)]
- public static void WriteLine(object value)
+ public static void WriteLine(object? value)
{
Out.WriteLine(value);
}
[MethodImplAttribute(MethodImplOptions.NoInlining)]
- public static void WriteLine(string value)
+ public static void WriteLine(string? value)
{
Out.WriteLine(value);
}
[MethodImplAttribute(MethodImplOptions.NoInlining)]
- public static void WriteLine(string format, object arg0)
+ public static void WriteLine(string format, object? arg0)
{
Out.WriteLine(format, arg0);
}
[MethodImplAttribute(MethodImplOptions.NoInlining)]
- public static void WriteLine(string format, object arg0, object arg1)
+ public static void WriteLine(string format, object? arg0, object? arg1)
{
Out.WriteLine(format, arg0, arg1);
}
[MethodImplAttribute(MethodImplOptions.NoInlining)]
- public static void WriteLine(string format, object arg0, object arg1, object arg2)
+ public static void WriteLine(string format, object? arg0, object? arg1, object? arg2)
{
Out.WriteLine(format, arg0, arg1, arg2);
}
[MethodImplAttribute(MethodImplOptions.NoInlining)]
- public static void WriteLine(string format, params object[] arg)
+ public static void WriteLine(string format, params object?[]? arg)
{
if (arg == null) // avoid ArgumentNullException from String.Format
Out.WriteLine(format, null, null); // faster than Out.WriteLine(format, (Object)arg);
}
[MethodImplAttribute(MethodImplOptions.NoInlining)]
- public static void Write(string format, object arg0)
+ public static void Write(string format, object? arg0)
{
Out.Write(format, arg0);
}
[MethodImplAttribute(MethodImplOptions.NoInlining)]
- public static void Write(string format, object arg0, object arg1)
+ public static void Write(string format, object? arg0, object? arg1)
{
Out.Write(format, arg0, arg1);
}
[MethodImplAttribute(MethodImplOptions.NoInlining)]
- public static void Write(string format, object arg0, object arg1, object arg2)
+ public static void Write(string format, object? arg0, object? arg1, object? arg2)
{
Out.Write(format, arg0, arg1, arg2);
}
[MethodImplAttribute(MethodImplOptions.NoInlining)]
- public static void Write(string format, params object[] arg)
+ public static void Write(string format, params object?[]? arg)
{
if (arg == null) // avoid ArgumentNullException from String.Format
Out.Write(format, null, null); // faster than Out.Write(format, (Object)arg);
}
[MethodImplAttribute(MethodImplOptions.NoInlining)]
- public static void Write(char[] buffer)
+ public static void Write(char[]? buffer)
{
Out.Write(buffer);
}
}
[MethodImplAttribute(MethodImplOptions.NoInlining)]
- public static void Write(object value)
+ public static void Write(object? value)
{
Out.Write(value);
}
[MethodImplAttribute(MethodImplOptions.NoInlining)]
- public static void Write(string value)
+ public static void Write(string? value)
{
Out.Write(value);
}
internal static bool HandleBreakEvent(ConsoleSpecialKey controlKey)
{
- ConsoleCancelEventHandler handler = s_cancelCallbacks;
+ ConsoleCancelEventHandler? handler = s_cancelCallbacks;
if (handler == null)
{
return false;
namespace System
{
- public delegate void ConsoleCancelEventHandler(object sender, ConsoleCancelEventArgs e);
+ public delegate void ConsoleCancelEventHandler(object? sender, ConsoleCancelEventArgs e);
public sealed class ConsoleCancelEventArgs : EventArgs
{
get { return _mods; }
}
- public override bool Equals(object value)
+ public override bool Equals(object? value)
{
return value is ConsoleKeyInfo && Equals((ConsoleKeyInfo)value);
}
get { return GetConsoleEncoding(); }
}
- private static SyncTextReader s_stdInReader;
+ private static SyncTextReader? s_stdInReader;
private static SyncTextReader StdInReader
{
if (Console.IsOutputRedirected)
return;
- string titleFormat = TerminalFormatStrings.Instance.Title;
+ string? titleFormat = TerminalFormatStrings.Instance.Title;
if (!string.IsNullOrEmpty(titleFormat))
{
string ansiStr = TermInfo.ParameterizedStrings.Evaluate(titleFormat, value);
return;
}
- string cursorAddressFormat = TerminalFormatStrings.Instance.CursorAddress;
+ string? cursorAddressFormat = TerminalFormatStrings.Instance.CursorAddress;
if (!string.IsNullOrEmpty(cursorAddressFormat))
{
string ansiStr = TermInfo.ParameterizedStrings.Evaluate(cursorAddressFormat, top, left);
/// <returns>The encoding.</returns>
private static Encoding GetConsoleEncoding()
{
- Encoding enc = EncodingHelper.GetEncodingFromCharset();
+ Encoding? enc = EncodingHelper.GetEncodingFromCharset();
return enc != null ?
enc.RemovePreamble() :
new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);
}
// We haven't yet computed a format string. Compute it, use it, then cache it.
- string formatString = foreground ? TerminalFormatStrings.Instance.Foreground : TerminalFormatStrings.Instance.Background;
+ string? formatString = foreground ? TerminalFormatStrings.Instance.Foreground : TerminalFormatStrings.Instance.Background;
if (!string.IsNullOrEmpty(formatString))
{
int maxColors = TerminalFormatStrings.Instance.MaxColors; // often 8 or 16; 0 is invalid
// the native lib later to handle signals that require re-entering the mode.
if (!Console.IsOutputRedirected)
{
- string keypadXmit = TerminalFormatStrings.Instance.KeypadXmit;
+ string? keypadXmit = TerminalFormatStrings.Instance.KeypadXmit;
if (keypadXmit != null)
{
Interop.Sys.SetKeypadXmit(keypadXmit);
private static readonly Lazy<TerminalFormatStrings> s_instance = new Lazy<TerminalFormatStrings>(() => new TerminalFormatStrings(TermInfo.Database.ReadActiveDatabase()));
/// <summary>The format string to use to change the foreground color.</summary>
- public readonly string Foreground;
+ public readonly string? Foreground;
/// <summary>The format string to use to change the background color.</summary>
- public readonly string Background;
+ public readonly string? Background;
/// <summary>The format string to use to reset the foreground and background colors.</summary>
- public readonly string Reset;
+ public readonly string? Reset;
/// <summary>The maximum number of colors supported by the terminal.</summary>
public readonly int MaxColors;
/// <summary>The number of columns in a format.</summary>
/// <summary>The number of lines in a format.</summary>
public readonly int Lines;
/// <summary>The format string to use to make cursor visible.</summary>
- public readonly string CursorVisible;
+ public readonly string? CursorVisible;
/// <summary>The format string to use to make cursor invisible</summary>
- public readonly string CursorInvisible;
+ public readonly string? CursorInvisible;
/// <summary>The format string to use to set the window title.</summary>
- public readonly string Title;
+ public readonly string? Title;
/// <summary>The format string to use for an audible bell.</summary>
- public readonly string Bell;
+ public readonly string? Bell;
/// <summary>The format string to use to clear the terminal.</summary>
- public readonly string Clear;
+ public readonly string? Clear;
/// <summary>The format string to use to set the position of the cursor.</summary>
- public readonly string CursorAddress;
+ public readonly string? CursorAddress;
/// <summary>The format string to use to move the cursor to the left.</summary>
- public readonly string CursorLeft;
+ public readonly string? CursorLeft;
/// <summary>The format string to use to clear to the end of line.</summary>
- public readonly string ClrEol;
+ public readonly string? ClrEol;
/// <summary>The ANSI-compatible string for the Cursor Position report request.</summary>
/// <remarks>
/// This should really be in user string 7 in the terminfo file, but some terminfo databases
/// <summary> Min key length </summary>
public readonly int MinKeyFormatLength;
/// <summary>The ANSI string used to enter "application" / "keypad transmit" mode.</summary>
- public readonly string KeypadXmit;
+ public readonly string? KeypadXmit;
- public TerminalFormatStrings(TermInfo.Database db)
+ public TerminalFormatStrings(TermInfo.Database? db)
{
if (db == null)
return;
private static string GetTitle(TermInfo.Database db)
{
// Try to get the format string from tsl/fsl and use it if they're available
- string tsl = db.GetString(TermInfo.WellKnownStrings.ToStatusLine);
- string fsl = db.GetString(TermInfo.WellKnownStrings.FromStatusLine);
+ string? tsl = db.GetString(TermInfo.WellKnownStrings.ToStatusLine);
+ string? fsl = db.GetString(TermInfo.WellKnownStrings.FromStatusLine);
if (tsl != null && fsl != null)
{
return tsl + "%p1%s" + fsl;
private void AddKey(TermInfo.Database db, TermInfo.WellKnownStrings keyId, ConsoleKey key, bool shift, bool alt, bool control)
{
- string keyFormat = db.GetString(keyId);
+ string? keyFormat = db.GetString(keyId);
if (!string.IsNullOrEmpty(keyFormat))
KeyFormatToConsoleKey[keyFormat] = new ConsoleKeyInfo('\0', key, shift, alt, control);
}
private void AddKey(TermInfo.Database db, string extendedName, ConsoleKey key, bool shift, bool alt, bool control)
{
- string keyFormat = db.GetExtendedString(extendedName);
+ string? keyFormat = db.GetExtendedString(extendedName);
if (!string.IsNullOrEmpty(keyFormat))
KeyFormatToConsoleKey[keyFormat] = new ConsoleKeyInfo('\0', key, shift, alt, control);
}
/// <summary>Writes a terminfo-based ANSI escape string to stdout.</summary>
/// <param name="value">The string to write.</param>
/// <param name="mayChangeCursorPosition">Writing this value may change the cursor position.</param>
- internal static unsafe void WriteStdoutAnsiString(string value, bool mayChangeCursorPosition = true)
+ internal static unsafe void WriteStdoutAnsiString(string? value, bool mayChangeCursorPosition = true)
{
if (string.IsNullOrEmpty(value))
return;
handlerThread.Start(ctrlCode);
}
- private static void HandleBreakEvent(object state)
+ private static void HandleBreakEvent(object? state)
{
+ Debug.Assert(state != null);
var ctrlCode = (Interop.Sys.CtrlCode)state;
ConsoleSpecialKey controlKey = (ctrlCode == Interop.Sys.CtrlCode.Break ? ConsoleSpecialKey.ControlBreak : ConsoleSpecialKey.ControlC);
bool cancel = Console.HandleBreakEvent(controlKey);
*/
internal sealed class StdInReader : TextReader
{
- private static string s_moveLeftString; // string written to move the cursor to the left
- private static string s_clearToEol; // string written to clear from cursor to end of line
+ private static string? s_moveLeftString; // string written to move the cursor to the left
+ private static string? s_clearToEol; // string written to clear from cursor to end of line
private readonly StringBuilder _readLineSB; // SB that holds readLine output. This is a field simply to enable reuse; it's only used in ReadLine.
private readonly Stack<ConsoleKeyInfo> _tmpKeys = new Stack<ConsoleKeyInfo>(); // temporary working stack; should be empty outside of ReadLine
return result;
}
- public override string ReadLine()
+ public override string? ReadLine()
{
return ReadLine(consumeKeys: true);
}
- private string ReadLine(bool consumeKeys)
+ private string? ReadLine(bool consumeKeys)
{
Debug.Assert(_tmpKeys.Count == 0);
- string readLineStr = null;
+ string? readLineStr = null;
Interop.Sys.InitializeConsoleBeforeRead();
try
{
if (s_moveLeftString == null)
{
- string moveLeft = ConsolePal.TerminalFormatStrings.Instance.CursorLeft;
+ string? moveLeft = ConsolePal.TerminalFormatStrings.Instance.CursorLeft;
s_moveLeftString = !string.IsNullOrEmpty(moveLeft) ? moveLeft + " " + moveLeft : string.Empty;
}
}
}
- public override string ReadLine()
+ public override string? ReadLine()
{
lock (this)
{
// No explicit locking is needed, as they all just delegate
//
- public override Task<string> ReadLineAsync()
+ public override Task<string?> ReadLineAsync()
{
return Task.FromResult(ReadLine());
}
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Text;
using Microsoft.Win32.SafeHandles;
/// <summary>Read the database for the current terminal as specified by the "TERM" environment variable.</summary>
/// <returns>The database, or null if it could not be found.</returns>
- internal static Database ReadActiveDatabase()
+ internal static Database? ReadActiveDatabase()
{
- string term = Environment.GetEnvironmentVariable("TERM");
+ string? term = Environment.GetEnvironmentVariable("TERM");
return !string.IsNullOrEmpty(term) ? ReadDatabase(term) : null;
}
/// <summary>Read the database for the specified terminal.</summary>
/// <param name="term">The identifier for the terminal.</param>
/// <returns>The database, or null if it could not be found.</returns>
- private static Database ReadDatabase(string term)
+ private static Database? ReadDatabase(string term)
{
// This follows the same search order as prescribed by ncurses.
- Database db;
+ Database? db;
// First try a location specified in the TERMINFO environment variable.
- string terminfo = Environment.GetEnvironmentVariable("TERMINFO");
+ string? terminfo = Environment.GetEnvironmentVariable("TERMINFO");
if (!string.IsNullOrWhiteSpace(terminfo) && (db = ReadDatabase(term, terminfo)) != null)
{
return db;
}
// Then try in the user's home directory.
- string home = PersistedFiles.GetHomeDirectory();
+ string? home = PersistedFiles.GetHomeDirectory();
if (!string.IsNullOrWhiteSpace(home) && (db = ReadDatabase(term, home + "/.terminfo")) != null)
{
return db;
/// <param name="filePath">The path to the file to open.</param>
/// <param name="fd">If successful, the opened file descriptor; otherwise, -1.</param>
/// <returns>true if the file was successfully opened; otherwise, false.</returns>
- private static bool TryOpen(string filePath, out SafeFileHandle fd)
+ private static bool TryOpen(string filePath, [NotNullWhen(true)] out SafeFileHandle? fd)
{
fd = Interop.Sys.Open(filePath, Interop.Sys.OpenFlags.O_RDONLY | Interop.Sys.OpenFlags.O_CLOEXEC, 0);
if (fd.IsInvalid)
/// <param name="term">The identifier for the terminal.</param>
/// <param name="directoryPath">The path to the directory containing terminfo database files.</param>
/// <returns>The database, or null if it could not be found.</returns>
- private static Database ReadDatabase(string term, string directoryPath)
+ private static Database? ReadDatabase(string? term, string? directoryPath)
{
if (string.IsNullOrEmpty(term) || string.IsNullOrEmpty(directoryPath))
{
return null;
}
- SafeFileHandle fd;
+ SafeFileHandle? fd;
if (!TryOpen(directoryPath + "/" + term[0].ToString() + "/" + term, out fd) && // /directory/termFirstLetter/term (Linux)
!TryOpen(directoryPath + "/" + ((int)term[0]).ToString("X") + "/" + term, out fd)) // /directory/termFirstLetterAsHex/term (Mac)
{
/// <summary>Gets a string from the strings section by the string's well-known index.</summary>
/// <param name="stringTableIndex">The index of the string to find.</param>
/// <returns>The string if it's in the database; otherwise, null.</returns>
- public string GetString(WellKnownStrings stringTableIndex)
+ public string? GetString(WellKnownStrings stringTableIndex)
{
int index = (int)stringTableIndex;
Debug.Assert(index >= 0);
/// <summary>Gets a string from the extended strings section.</summary>
/// <param name="name">The name of the string as contained in the extended names section.</param>
/// <returns>The string if it's in the database; otherwise, null.</returns>
- public string GetExtendedString(string name)
+ public string? GetExtendedString(string name)
{
Debug.Assert(name != null);
- string value;
+ string? value;
return _extendedStrings.TryGetValue(name, out value) ?
value :
null;
/// defined as the earlier portions, and may not even exist, the parsing is more lenient about
/// errors, returning an empty collection rather than throwing.
/// </returns>
- private static Dictionary<string, string> ParseExtendedStrings(byte[] data, int extendedBeginning, bool readAs32Bit)
+ private static Dictionary<string, string>? ParseExtendedStrings(byte[] data, int extendedBeginning, bool readAs32Bit)
{
const int ExtendedHeaderSize = 10;
int sizeOfIntValuesInBytes = (readAs32Bit) ? 4 : 2;
{
/// <summary>A cached stack to use to avoid allocating a new stack object for every evaluation.</summary>
[ThreadStatic]
- private static Stack<FormatParam> t_cachedStack;
+ private static Stack<FormatParam>? t_cachedStack;
/// <summary>A cached array of arguments to use to avoid allocating a new array object for every evaluation.</summary>
[ThreadStatic]
- private static FormatParam[] t_cachedOneElementArgsArray;
+ private static FormatParam[]? t_cachedOneElementArgsArray;
/// <summary>A cached array of arguments to use to avoid allocating a new array object for every evaluation.</summary>
[ThreadStatic]
- private static FormatParam[] t_cachedTwoElementArgsArray;
+ private static FormatParam[]? t_cachedTwoElementArgsArray;
/// <summary>Evaluates a terminfo formatting string, using the supplied argument.</summary>
/// <param name="format">The format string.</param>
/// <returns>The formatted string.</returns>
public static string Evaluate(string format, FormatParam arg)
{
- FormatParam[] args = t_cachedOneElementArgsArray;
+ FormatParam[]? args = t_cachedOneElementArgsArray;
if (args == null)
{
t_cachedOneElementArgsArray = args = new FormatParam[1];
/// <returns>The formatted string.</returns>
public static string Evaluate(string format, FormatParam arg1, FormatParam arg2)
{
- FormatParam[] args = t_cachedTwoElementArgsArray;
+ FormatParam[]? args = t_cachedTwoElementArgsArray;
if (args == null)
{
t_cachedTwoElementArgsArray = args = new FormatParam[2];
}
// Initialize the stack to use for processing.
- Stack<FormatParam> stack = t_cachedStack;
+ Stack<FormatParam>? stack = t_cachedStack;
if (stack == null)
{
t_cachedStack = stack = new Stack<FormatParam>();
// "dynamic" and "static" variables are much less often used (the "dynamic" and "static"
// terminology appears to just refer to two different collections rather than to any semantic
// meaning). As such, we'll only initialize them if we really need them.
- FormatParam[] dynamicVars = null, staticVars = null;
+ FormatParam[]? dynamicVars = null, staticVars = null;
int pos = 0;
return EvaluateInternal(format, ref pos, args, stack, ref dynamicVars, ref staticVars);
/// </returns>
private static string EvaluateInternal(
string format, ref int pos, FormatParam[] args, Stack<FormatParam> stack,
- ref FormatParam[] dynamicVars, ref FormatParam[] staticVars)
+ 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,
Debug.Assert(arg is string || arg is int);
// Determine how much space is needed to store the formatted string.
- string stringArg = arg as string;
+ string? stringArg = arg as string;
int neededLength = stringArg != null ?
Interop.Sys.SNPrintF(null, 0, format, stringArg) :
Interop.Sys.SNPrintF(null, 0, format, (int)arg);
/// <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)
+ char c, ref FormatParam[]? dynamicVars, ref FormatParam[]? staticVars, out int index)
{
if (c >= 'A' && c <= 'Z')
{
/// <summary>The integer stored in the parameter.</summary>
private readonly int _int32;
/// <summary>The string stored in the parameter.</summary>
- private readonly string _string; // null means an Int32 is stored
+ private readonly string? _string; // null means an Int32 is stored
/// <summary>Initializes the parameter with an integer value.</summary>
/// <param name="value">The value to be stored in the parameter.</param>
/// <summary>Initializes the parameter with a string value.</summary>
/// <param name="value">The value to be stored in the parameter.</param>
- public FormatParam(string value) : this(0, value ?? string.Empty) { }
+ public FormatParam(string? value) : this(0, value ?? string.Empty) { }
/// <summary>Initializes the parameter.</summary>
/// <param name="intValue">The integer value.</param>
/// <param name="stringValue">The string value.</param>
- private FormatParam(int intValue, string stringValue)
+ private FormatParam(int intValue, string? stringValue)
{
_int32 = intValue;
_string = stringValue;
}
/// <summary>Implicit converts a string into a parameter.</summary>
- public static implicit operator FormatParam(string value)
+ public static implicit operator FormatParam(string? value)
{
return new FormatParam(value);
}