| // CommandLineParser.cpp |
| |
| #include "StdAfx.h" |
| |
| #include "CommandLineParser.h" |
| |
| namespace NCommandLineParser { |
| |
| #ifdef _WIN32 |
| 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; |
| } |
| } |
| #endif |
| |
| 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; |
| } |
| |
| } |