Files
WPinternals/7zip/Common/CommandLineParser.cs
T
Gustave Monce c5fcb1ec8d Implement Qualcomm Sahara VIP and fix a few bugs
* Qualcomm Sahara VIP
* Project Cleanup
* Allow unlocking an already unlocked phone
2021-08-11 14:33:49 +02:00

326 lines
11 KiB
C#

// CommandLineParser.cs
using System;
using System.Collections;
namespace SevenZip.CommandLineParser
{
public enum SwitchType
{
Simple,
PostMinus,
LimitedPostString,
UnLimitedPostString,
PostChar
}
public class SwitchForm
{
public string IDString;
public SwitchType Type;
public bool Multi;
public int MinLen;
public int MaxLen;
public string PostCharSet;
public SwitchForm(string idString, SwitchType type, bool multi,
int minLen, int maxLen, string postCharSet)
{
IDString = idString;
Type = type;
Multi = multi;
MinLen = minLen;
MaxLen = maxLen;
PostCharSet = postCharSet;
}
public SwitchForm(string idString, SwitchType type, bool multi, int minLen) :
this(idString, type, multi, minLen, 0, "")
{
}
public SwitchForm(string idString, SwitchType type, bool multi) :
this(idString, type, multi, 0)
{
}
}
public class SwitchResult
{
public bool ThereIs;
public bool WithMinus;
public ArrayList PostStrings = new();
public int PostCharIndex;
public SwitchResult()
{
ThereIs = false;
}
}
public class Parser
{
public ArrayList NonSwitchStrings = new();
private readonly SwitchResult[] _switches;
public Parser(int numSwitches)
{
_switches = new SwitchResult[numSwitches];
for (int i = 0; i < numSwitches; i++)
{
_switches[i] = new SwitchResult();
}
}
private bool ParseString(string srcString, SwitchForm[] switchForms)
{
int len = srcString.Length;
if (len == 0)
{
return false;
}
int pos = 0;
if (!IsItSwitchChar(srcString[pos]))
{
return false;
}
while (pos < len)
{
if (IsItSwitchChar(srcString[pos]))
{
pos++;
}
const int kNoLen = -1;
int matchedSwitchIndex = 0;
int maxLen = kNoLen;
for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++)
{
int switchLen = switchForms[switchIndex].IDString.Length;
if (switchLen <= maxLen || pos + switchLen > len)
{
continue;
}
if (String.Compare(switchForms[switchIndex].IDString, 0,
srcString, pos, switchLen, true) == 0)
{
matchedSwitchIndex = switchIndex;
maxLen = switchLen;
}
}
if (maxLen == kNoLen)
{
throw new Exception("maxLen == kNoLen");
}
SwitchResult matchedSwitch = _switches[matchedSwitchIndex];
SwitchForm switchForm = switchForms[matchedSwitchIndex];
if ((!switchForm.Multi) && matchedSwitch.ThereIs)
{
throw new Exception("switch must be single");
}
matchedSwitch.ThereIs = true;
pos += maxLen;
int tailSize = len - pos;
SwitchType type = switchForm.Type;
switch (type)
{
case SwitchType.PostMinus:
{
if (tailSize == 0)
{
matchedSwitch.WithMinus = false;
}
else
{
matchedSwitch.WithMinus = srcString[pos] == kSwitchMinus;
if (matchedSwitch.WithMinus)
{
pos++;
}
}
break;
}
case SwitchType.PostChar:
{
if (tailSize < switchForm.MinLen)
{
throw new Exception("switch is not full");
}
string charSet = switchForm.PostCharSet;
const int kEmptyCharValue = -1;
if (tailSize == 0)
{
matchedSwitch.PostCharIndex = kEmptyCharValue;
}
else
{
int index = charSet.IndexOf(srcString[pos]);
if (index < 0)
{
matchedSwitch.PostCharIndex = kEmptyCharValue;
}
else
{
matchedSwitch.PostCharIndex = index;
pos++;
}
}
break;
}
case SwitchType.LimitedPostString:
case SwitchType.UnLimitedPostString:
{
int minLen = switchForm.MinLen;
if (tailSize < minLen)
{
throw new Exception("switch is not full");
}
if (type == SwitchType.UnLimitedPostString)
{
matchedSwitch.PostStrings.Add(srcString[pos..]);
return true;
}
String stringSwitch = srcString.Substring(pos, minLen);
pos += minLen;
for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++)
{
char c = srcString[pos];
if (IsItSwitchChar(c))
{
break;
}
stringSwitch += c;
}
matchedSwitch.PostStrings.Add(stringSwitch);
break;
}
}
}
return true;
}
public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings)
{
int numCommandStrings = commandStrings.Length;
bool stopSwitch = false;
for (int i = 0; i < numCommandStrings; i++)
{
string s = commandStrings[i];
if (stopSwitch)
{
NonSwitchStrings.Add(s);
}
else
if (s == kStopSwitchParsing)
{
stopSwitch = true;
}
else
if (!ParseString(s, switchForms))
{
NonSwitchStrings.Add(s);
}
}
}
public SwitchResult this[int index] { get { return _switches[index]; } }
public static int ParseCommand(CommandForm[] commandForms, string commandString,
out string postString)
{
for (int i = 0; i < commandForms.Length; i++)
{
string id = commandForms[i].IDString;
if (commandForms[i].PostStringMode)
{
if (commandString.IndexOf(id) == 0)
{
postString = commandString[id.Length..];
return i;
}
}
else
if (commandString == id)
{
postString = "";
return i;
}
}
postString = "";
return -1;
}
private static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms,
string commandString, ArrayList indices)
{
indices.Clear();
int numUsedChars = 0;
for (int i = 0; i < numForms; i++)
{
CommandSubCharsSet charsSet = forms[i];
int currentIndex = -1;
int len = charsSet.Chars.Length;
for (int j = 0; j < len; j++)
{
char c = charsSet.Chars[j];
int newIndex = commandString.IndexOf(c);
if (newIndex >= 0)
{
if (currentIndex >= 0)
{
return false;
}
if (commandString.IndexOf(c, newIndex + 1) >= 0)
{
return false;
}
currentIndex = j;
numUsedChars++;
}
}
if (currentIndex == -1 && !charsSet.EmptyAllowed)
{
return false;
}
indices.Add(currentIndex);
}
return numUsedChars == commandString.Length;
}
private const char kSwitchID1 = '-';
private const char kSwitchID2 = '/';
private const char kSwitchMinus = '-';
private const string kStopSwitchParsing = "--";
private static bool IsItSwitchChar(char c)
{
return c == kSwitchID1 || c == kSwitchID2;
}
}
public class CommandForm
{
public string IDString = "";
public bool PostStringMode = false;
public CommandForm(string idString, bool postStringMode)
{
IDString = idString;
PostStringMode = postStringMode;
}
}
internal class CommandSubCharsSet
{
public string Chars = "";
public bool EmptyAllowed = false;
}
}