// 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; | |
} | |
} |