You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

275 lines
6.8 KiB

// 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 ArrayList();
public int PostCharIndex;
public SwitchResult()
{
ThereIs = false;
}
}
public class Parser
{
public ArrayList NonSwitchStrings = new ArrayList();
SwitchResult[] _switches;
public Parser(int numSwitches)
{
_switches = new SwitchResult[numSwitches];
for (int i = 0; i < numSwitches; i++)
_switches[i] = new SwitchResult();
}
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.Substring(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.Substring(id.Length);
return i;
}
}
else
if (commandString == id)
{
postString = "";
return i;
}
}
postString = "";
return -1;
}
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);
}
const char kSwitchID1 = '-';
const char kSwitchID2 = '/';
const char kSwitchMinus = '-';
const string kStopSwitchParsing = "--";
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;
}
}
class CommandSubCharsSet
{
public string Chars = "";
public bool EmptyAllowed = false;
}
}