// 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;
int i;
for (i = 0; i < src.Length(); i++)
{
wchar_t c = src[i];
if (c == L' ' && !quoteMode)
{
dest2 = src.Mid(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 wchar_t kSwitchID1 = '-';
// static const wchar_t kSwitchID2 = '/';
static const wchar_t kSwitchMinus = '-';
static const wchar_t *kStopSwitchParsing = L"--";
static bool IsItSwitchChar(wchar_t c)
{
return (c == kSwitchID1 /*|| c == kSwitchID2 */);
}
CParser::CParser(int numSwitches):
_numSwitches(numSwitches)
{
_switches = new CSwitchResult[_numSwitches];
}
CParser::~CParser()
{
delete []_switches;
}
void CParser::ParseStrings(const CSwitchForm *switchForms,
const UStringVector &commandStrings)
{
int numCommandStrings = commandStrings.Size();
bool stopSwitch = false;
for (int i = 0; i < numCommandStrings; i++)
{
const UString &s = commandStrings[i];
if (stopSwitch)
NonSwitchStrings.Add(s);
else
if (s == kStopSwitchParsing)
stopSwitch = true;
else
if (!ParseString(s, switchForms))
NonSwitchStrings.Add(s);
}
}
// if string contains switch then function updates switch structures
// out: (string is a switch)
bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms)
{
int len = s.Length();
if (len == 0)
return false;
int pos = 0;
if (!IsItSwitchChar(s[pos]))
return false;
while (pos < len)
{
if (IsItSwitchChar(s[pos]))
pos++;
const int kNoLen = -1;
int matchedSwitchIndex = 0; // GCC Warning
int maxLen = kNoLen;
for (int switchIndex = 0; switchIndex < _numSwitches; switchIndex++)
{
int switchLen = MyStringLen(switchForms[switchIndex].IDString);
if (switchLen <= maxLen || pos + switchLen > len)
continue;
UString temp = s + pos;
temp = temp.Left(switchLen);
if (temp.CompareNoCase(switchForms[switchIndex].IDString) == 0)
// if (_strnicmp(switchForms[switchIndex].IDString, LPCSTR(s) + pos, switchLen) == 0)
{
matchedSwitchIndex = switchIndex;
maxLen = switchLen;
}
}
if (maxLen == kNoLen)
throw "maxLen == kNoLen";
CSwitchResult &matchedSwitch = _switches[matchedSwitchIndex];
const CSwitchForm &switchForm = switchForms[matchedSwitchIndex];
if ((!switchForm.Multi) && matchedSwitch.ThereIs)
throw "switch must be single";
matchedSwitch.ThereIs = true;
pos += maxLen;
int tailSize = len - pos;
NSwitchType::EEnum type = switchForm.Type;
switch(type)
{
case NSwitchType::kPostMinus:
{
if (tailSize == 0)
matchedSwitch.WithMinus = false;
else
{
matchedSwitch.WithMinus = (s[pos] == kSwitchMinus);
if (matchedSwitch.WithMinus)
pos++;
}
break;
}
case NSwitchType::kPostChar:
{
if (tailSize < switchForm.MinLen)
throw "switch is not full";
UString set = switchForm.PostCharSet;
const int kEmptyCharValue = -1;
if (tailSize == 0)
matchedSwitch.PostCharIndex = kEmptyCharValue;
else
{
int index = set.Find(s[pos]);
if (index < 0)
matchedSwitch.PostCharIndex = kEmptyCharValue;
else
{
matchedSwitch.PostCharIndex = index;
pos++;
}
}
break;
}
case NSwitchType::kLimitedPostString:
case NSwitchType::kUnLimitedPostString:
{
int minLen = switchForm.MinLen;
if (tailSize < minLen)
throw "switch is not full";
if (type == NSwitchType::kUnLimitedPostString)
{
matchedSwitch.PostStrings.Add(s.Mid(pos));
return true;
}
int maxLen = switchForm.MaxLen;
UString stringSwitch = s.Mid(pos, minLen);
pos += minLen;
for (int i = minLen; i < maxLen && pos < len; i++, pos++)
{
wchar_t c = s[pos];
if (IsItSwitchChar(c))
break;
stringSwitch += c;
}
matchedSwitch.PostStrings.Add(stringSwitch);
break;
}
case NSwitchType::kSimple:
break;
}
}
return true;
}
const CSwitchResult& CParser::operator[](size_t index) const
{
return _switches[index];
}
/////////////////////////////////
// Command parsing procedures
int ParseCommand(int numCommandForms, const CCommandForm *commandForms,
const UString &commandString, UString &postString)
{
for (int i = 0; i < numCommandForms; i++)
{
const UString id = commandForms[i].IDString;
if (commandForms[i].PostStringMode)
{
if (commandString.Find(id) == 0)
{
postString = commandString.Mid(id.Length());
return i;
}
}
else
if (commandString == id)
{
postString.Empty();
return i;
}
}
return -1;
}
}