blob: 94aabce6dd47d4185dc9d72d6c16987b7ded8b70 [file] [log] [blame]
// CommandLineParser.cpp
#include "StdAfx.h"
#include "CommandLineParser.h"
namespace NCommandLineParser {
bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2)
{
dest1.Empty();
dest2.Empty();
bool quoteMode = false;
unsigned i;
for (i = 0; i < src.Len(); i++)
{
wchar_t c = src[i];
if ((c == L' ' || c == L'\t') && !quoteMode)
{
dest2 = src.Ptr(i + 1);
return i != 0;
}
if (c == L'\"')
quoteMode = !quoteMode;
else
dest1 += c;
}
return i != 0;
}
void SplitCommandLine(const UString &s, UStringVector &parts)
{
UString sTemp (s);
sTemp.Trim();
parts.Clear();
for (;;)
{
UString s1, s2;
if (SplitCommandLine(sTemp, s1, s2))
parts.Add(s1);
if (s2.IsEmpty())
break;
sTemp = s2;
}
}
static const char * const kStopSwitchParsing = "--";
static bool inline IsItSwitchChar(wchar_t c)
{
return (c == '-');
}
CParser::CParser():
_switches(NULL),
StopSwitchIndex(-1)
{
}
CParser::~CParser()
{
delete []_switches;
}
// if (s) contains switch then function updates switch structures
// out: true, if (s) is a switch
bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms, unsigned numSwitches)
{
if (s.IsEmpty() || !IsItSwitchChar(s[0]))
return false;
unsigned pos = 1;
unsigned switchIndex = 0;
int maxLen = -1;
for (unsigned i = 0; i < numSwitches; i++)
{
const char * const key = switchForms[i].Key;
unsigned switchLen = MyStringLen(key);
if ((int)switchLen <= maxLen || pos + switchLen > s.Len())
continue;
if (IsString1PrefixedByString2_NoCase_Ascii((const wchar_t *)s + pos, key))
{
switchIndex = i;
maxLen = switchLen;
}
}
if (maxLen < 0)
{
ErrorMessage = "Unknown switch:";
return false;
}
pos += maxLen;
CSwitchResult &sw = _switches[switchIndex];
const CSwitchForm &form = switchForms[switchIndex];
if (!form.Multi && sw.ThereIs)
{
ErrorMessage = "Multiple instances for switch:";
return false;
}
sw.ThereIs = true;
int rem = s.Len() - pos;
if (rem < form.MinLen)
{
ErrorMessage = "Too short switch:";
return false;
}
sw.WithMinus = false;
sw.PostCharIndex = -1;
switch (form.Type)
{
case NSwitchType::kMinus:
if (rem == 1)
{
sw.WithMinus = (s[pos] == '-');
if (sw.WithMinus)
return true;
ErrorMessage = "Incorrect switch postfix:";
return false;
}
break;
case NSwitchType::kChar:
if (rem == 1)
{
wchar_t c = s[pos];
if (c <= 0x7F)
{
sw.PostCharIndex = FindCharPosInString(form.PostCharSet, (char)c);
if (sw.PostCharIndex >= 0)
return true;
}
ErrorMessage = "Incorrect switch postfix:";
return false;
}
break;
case NSwitchType::kString:
{
sw.PostStrings.Add(s.Ptr(pos));
return true;
}
}
if (pos != s.Len())
{
ErrorMessage = "Too long switch:";
return false;
}
return true;
}
bool CParser::ParseStrings(const CSwitchForm *switchForms, unsigned numSwitches, const UStringVector &commandStrings)
{
StopSwitchIndex = -1;
ErrorMessage.Empty();
ErrorLine.Empty();
NonSwitchStrings.Clear();
delete []_switches;
_switches = NULL;
_switches = new CSwitchResult[numSwitches];
FOR_VECTOR (i, commandStrings)
{
const UString &s = commandStrings[i];
if (StopSwitchIndex < 0)
{
if (s.IsEqualTo(kStopSwitchParsing))
{
StopSwitchIndex = NonSwitchStrings.Size();
continue;
}
if (!s.IsEmpty() && IsItSwitchChar(s[0]))
{
if (ParseString(s, switchForms, numSwitches))
continue;
ErrorLine = s;
return false;
}
}
NonSwitchStrings.Add(s);
}
return true;
}
}