// CommandLineParser.cpp #include "StdAfx.h" #include "CommandLineParser.h" static bool IsString1PrefixedByString2_NoCase(const wchar_t *u, const char *a) { for (;;) { char c = *a; if (c == 0) return true; if (MyCharLower_Ascii(c) != MyCharLower_Ascii(*u)) return false; a++; u++; } } namespace NCommandLineParser { #ifdef _WIN32 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; } } #endif static const char *kStopSwitchParsing = "--"; static bool inline IsItSwitchChar(wchar_t c) { return (c == '-'); } CParser::CParser(unsigned numSwitches): _numSwitches(numSwitches), _switches(0) { _switches = new CSwitchResult[numSwitches]; } 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) { 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 *key = switchForms[i].Key; unsigned switchLen = MyStringLen(key); if ((int)switchLen <= maxLen || pos + switchLen > s.Len()) continue; if (IsString1PrefixedByString2_NoCase((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 != 0) { sw.WithMinus = (s[pos] == '-'); if (sw.WithMinus) pos++; } break; case NSwitchType::kChar: if (rem != 0) { wchar_t c = s[pos]; if (c <= 0x7F) { sw.PostCharIndex = FindCharPosInString(form.PostCharSet, (char)c); if (sw.PostCharIndex >= 0) pos++; } } break; case NSwitchType::kString: sw.PostStrings.Add((const wchar_t *)s + pos); return true; } if (pos != s.Len()) { ErrorMessage = "Too long switch:"; return false; } return true; } bool CParser::ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings) { ErrorLine.Empty(); bool stopSwitch = false; FOR_VECTOR (i, commandStrings) { const UString &s = commandStrings[i]; if (!stopSwitch) { if (s.IsEqualTo(kStopSwitchParsing)) { stopSwitch = true; continue; } if (!s.IsEmpty() && IsItSwitchChar(s[0])) { if (ParseString(s, switchForms)) continue; ErrorLine = s; return false; } } NonSwitchStrings.Add(s); } return true; } }