Files
sbox-public/engine/Sandbox.System/Utility/CommandLine.cs
s&box team 71f266059a Open source release
This commit imports the C# engine code and game files, excluding C++ source code.

[Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
2025-11-24 09:05:18 +00:00

150 lines
4.3 KiB
C#

namespace Sandbox.Utility;
/// <summary>
/// Parses command line arguments into switches with optional values.
/// Supports both +switch and -switch syntax with optional values.
/// Example: -console +map "de_dust" -maxplayers 32
/// </summary>
internal static class CommandLine
{
private static readonly Dictionary<string, string> switches = new( StringComparer.OrdinalIgnoreCase );
private static string commandLine = "";
/// <summary>
/// Returns the full command line string.
/// </summary>
public static string Full => commandLine;
/// <summary>
/// Allows unit tests to override the command line string.
/// If null, uses Environment.CommandLine.
/// </summary>
internal static string CommandLineString { get; set; }
static CommandLine()
{
Parse();
}
/// <summary>
/// Parses the command line into a dictionary of switches and values.
/// Call this again if CommandLineString is modified.
/// </summary>
public static void Parse()
{
commandLine = CommandLineString ?? Environment.CommandLine;
if ( string.IsNullOrEmpty( commandLine ) )
return;
var currentKey = "";
var inQuotes = false;
var quoteChar = '"';
var currentValue = new StringBuilder();
var isBuildingKey = false;
for ( var i = 0; i < commandLine.Length; i++ )
{
var c = commandLine[i];
// Handle quote toggling
if ( c == quoteChar )
{
inQuotes = !inQuotes;
currentValue.Append( c );
continue;
}
// Check if we can start a new switch (must be at start or after whitespace)
var canStartSwitch = i == 0 || char.IsWhiteSpace( commandLine[i - 1] );
// New switch detected ('+' or '-')
if ( canStartSwitch && !inQuotes && c is '+' or '-' )
{
// Save previous switch if it exists
if ( !string.IsNullOrEmpty( currentKey ) )
{
switches[currentKey] = currentValue.ToString().Trim();
}
// Reset for new switch
currentKey = "";
currentValue.Clear();
isBuildingKey = true;
continue;
}
// Handle whitespace
if ( !inQuotes && char.IsWhiteSpace( c ) )
{
// If we're still building the key, this ends it
if ( isBuildingKey )
{
isBuildingKey = false;
continue;
}
// Otherwise, preserve spaces in values
currentValue.Append( ' ' );
continue;
}
// Append character to either key or value
if ( isBuildingKey )
currentKey += c;
else
currentValue.Append( c );
}
// Save final switch
if ( !string.IsNullOrEmpty( currentKey ) )
{
switches[currentKey] = currentValue.ToString().Trim();
}
}
/// <summary>
/// Checks if a command line switch is present.
/// </summary>
/// <param name="strName">Switch name (with or without + or - prefix)</param>
/// <returns>True if the switch was specified on the command line</returns>
/// <example>if ( HasSwitch( "-console" ) ) EnableConsole();</example>
public static bool HasSwitch( string strName ) => switches.ContainsKey( strName.Trim( '+', '-' ) );
/// <summary>
/// Gets the value of a command line switch, or a default if not present.
/// </summary>
/// <param name="strName">Switch name (with or without + or - prefix)</param>
/// <param name="strDefault">Default value if switch not found</param>
/// <returns>The switch value or default</returns>
/// <example>map = GetSwitch( "+map", "de_dust" );</example>
public static string GetSwitch( string strName, string strDefault )
{
return switches.GetValueOrDefault( strName.Trim( '+', '-' ), strDefault );
}
/// <summary>
/// Gets the integer value of a command line switch, or a default if not present or invalid.
/// </summary>
/// <param name="strName">Switch name (with or without + or - prefix)</param>
/// <param name="iDefault">Default value if switch not found or not an integer</param>
/// <returns>The parsed integer value or default</returns>
/// <example>maxplayers = GetSwitchInt( "+maxplayers", 32 );</example>
public static int GetSwitchInt( string strName, int iDefault )
{
if ( !switches.TryGetValue( strName.Trim( '+', '-' ), out var strValue ) )
return iDefault;
return int.TryParse( strValue, out var outval ) ? outval : iDefault;
}
/// <summary>
/// Gets all parsed command line switches and their values.
/// </summary>
/// <returns>Dictionary of switch names to values (switch prefixes removed)</returns>
public static Dictionary<string, string> GetSwitches()
{
return switches;
}
}