mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-09-01 17:47:24 +02:00
134 lines
3.7 KiB
C#
134 lines
3.7 KiB
C#
using System;
|
|
using System.Buffers;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using Robust.Shared.Collections;
|
|
|
|
namespace Robust.Shared.Utility
|
|
{
|
|
public static class CommandParsing
|
|
{
|
|
private static readonly SearchValues<char> CommandArgumentSeparator = SearchValues.Create(" ");
|
|
|
|
/// <summary>
|
|
/// Parses a full console command into a list of arguments.
|
|
/// </summary>
|
|
/// <param name="text">Full input string.</param>
|
|
/// <param name="args">List of arguments to write into.</param>
|
|
public static void ParseArguments(ReadOnlySpan<char> text, List<string> args)
|
|
{
|
|
var ranges = new ValueList<(int, int)>();
|
|
ParseArguments(text, args, ref ranges);
|
|
}
|
|
|
|
internal static void ParseArguments(
|
|
ReadOnlySpan<char> text,
|
|
List<string> args,
|
|
ref ValueList<(int start, int end)> ranges)
|
|
{
|
|
var sb = new StringBuilder();
|
|
var inQuotes = false;
|
|
var startPos = -1;
|
|
|
|
for (var i = 0; i < text.Length; i++)
|
|
{
|
|
var chr = text[i];
|
|
if (chr == '\\')
|
|
{
|
|
i += 1;
|
|
startPos = i;
|
|
if (i == text.Length)
|
|
{
|
|
sb.Append('\\');
|
|
break;
|
|
}
|
|
|
|
sb.Append(text[i]);
|
|
continue;
|
|
}
|
|
|
|
if (chr == '"')
|
|
{
|
|
if (inQuotes)
|
|
{
|
|
args.Add(sb.ToString());
|
|
sb.Clear();
|
|
ranges.Add((startPos, i + 1));
|
|
startPos = -1;
|
|
}
|
|
else
|
|
{
|
|
if (startPos < 0)
|
|
startPos = i;
|
|
}
|
|
|
|
inQuotes = !inQuotes;
|
|
continue;
|
|
}
|
|
|
|
if (CommandArgumentSeparator.Contains(chr) && !inQuotes)
|
|
{
|
|
if (sb.Length != 0)
|
|
{
|
|
args.Add(sb.ToString());
|
|
sb.Clear();
|
|
ranges.Add((startPos, i));
|
|
startPos = -1;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
if (startPos < 0)
|
|
startPos = i;
|
|
|
|
sb.Append(chr);
|
|
}
|
|
|
|
if (sb.Length != 0)
|
|
{
|
|
args.Add(sb.ToString());
|
|
ranges.Add((startPos, text.Length));
|
|
}
|
|
}
|
|
|
|
public static string Escape(string text)
|
|
{
|
|
return text.Replace("\\", "\\\\").Replace("\"", "\\\"");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Split a set of arguments into a string that can be parsed round-trip.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// This is effectively the inverse of <see cref="ParseArguments"/>.
|
|
/// </para>
|
|
/// </remarks>
|
|
public static string EscapeCommand(params string[] arguments)
|
|
{
|
|
var sb = new StringBuilder();
|
|
|
|
var first = true;
|
|
|
|
foreach (var entry in arguments)
|
|
{
|
|
if (!first)
|
|
sb.Append(' ');
|
|
first = false;
|
|
|
|
var quoted = entry.ContainsAny(CommandArgumentSeparator);
|
|
if (quoted)
|
|
sb.Append('"');
|
|
|
|
sb.Append(Escape(entry));
|
|
|
|
if (quoted)
|
|
sb.Append('"');
|
|
}
|
|
|
|
return sb.ToString();
|
|
}
|
|
}
|
|
}
|