1// CommandLineParser.cpp 2 3#include "StdAfx.h" 4 5#include "CommandLineParser.h" 6 7namespace NCommandLineParser { 8 9void SplitCommandLine(const UString &src, UString &dest1, UString &dest2) 10{ 11 dest1.Empty(); 12 dest2.Empty(); 13 bool quoteMode = false; 14 int i; 15 for (i = 0; i < src.Length(); i++) 16 { 17 wchar_t c = src[i]; 18 if (c == L'\"') 19 quoteMode = !quoteMode; 20 else if (c == L' ' && !quoteMode) 21 { 22 i++; 23 break; 24 } 25 else 26 dest1 += c; 27 } 28 dest2 = src.Mid(i); 29} 30 31void SplitCommandLine(const UString &s, UStringVector &parts) 32{ 33 UString sTemp = s; 34 sTemp.Trim(); 35 parts.Clear(); 36 for (;;) 37 { 38 UString s1, s2; 39 SplitCommandLine(sTemp, s1, s2); 40 // s1.Trim(); 41 // s2.Trim(); 42 if (!s1.IsEmpty()) 43 parts.Add(s1); 44 if (s2.IsEmpty()) 45 break; 46 sTemp = s2; 47 } 48} 49 50 51static const wchar_t kSwitchID1 = '-'; 52// static const wchar_t kSwitchID2 = '/'; 53 54static const wchar_t kSwitchMinus = '-'; 55static const wchar_t *kStopSwitchParsing = L"--"; 56 57static bool IsItSwitchChar(wchar_t c) 58{ 59 return (c == kSwitchID1 /*|| c == kSwitchID2 */); 60} 61 62CParser::CParser(int numSwitches): 63 _numSwitches(numSwitches) 64{ 65 _switches = new CSwitchResult[_numSwitches]; 66} 67 68CParser::~CParser() 69{ 70 delete []_switches; 71} 72 73void CParser::ParseStrings(const CSwitchForm *switchForms, 74 const UStringVector &commandStrings) 75{ 76 int numCommandStrings = commandStrings.Size(); 77 bool stopSwitch = false; 78 for (int i = 0; i < numCommandStrings; i++) 79 { 80 const UString &s = commandStrings[i]; 81 if (stopSwitch) 82 NonSwitchStrings.Add(s); 83 else 84 if (s == kStopSwitchParsing) 85 stopSwitch = true; 86 else 87 if (!ParseString(s, switchForms)) 88 NonSwitchStrings.Add(s); 89 } 90} 91 92// if string contains switch then function updates switch structures 93// out: (string is a switch) 94bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms) 95{ 96 int len = s.Length(); 97 if (len == 0) 98 return false; 99 int pos = 0; 100 if (!IsItSwitchChar(s[pos])) 101 return false; 102 while(pos < len) 103 { 104 if (IsItSwitchChar(s[pos])) 105 pos++; 106 const int kNoLen = -1; 107 int matchedSwitchIndex = 0; // GCC Warning 108 int maxLen = kNoLen; 109 for(int switchIndex = 0; switchIndex < _numSwitches; switchIndex++) 110 { 111 int switchLen = MyStringLen(switchForms[switchIndex].IDString); 112 if (switchLen <= maxLen || pos + switchLen > len) 113 continue; 114 115 UString temp = s + pos; 116 temp = temp.Left(switchLen); 117 if(temp.CompareNoCase(switchForms[switchIndex].IDString) == 0) 118 // if(_strnicmp(switchForms[switchIndex].IDString, LPCSTR(s) + pos, switchLen) == 0) 119 { 120 matchedSwitchIndex = switchIndex; 121 maxLen = switchLen; 122 } 123 } 124 if (maxLen == kNoLen) 125 throw "maxLen == kNoLen"; 126 CSwitchResult &matchedSwitch = _switches[matchedSwitchIndex]; 127 const CSwitchForm &switchForm = switchForms[matchedSwitchIndex]; 128 if ((!switchForm.Multi) && matchedSwitch.ThereIs) 129 throw "switch must be single"; 130 matchedSwitch.ThereIs = true; 131 pos += maxLen; 132 int tailSize = len - pos; 133 NSwitchType::EEnum type = switchForm.Type; 134 switch(type) 135 { 136 case NSwitchType::kPostMinus: 137 { 138 if (tailSize == 0) 139 matchedSwitch.WithMinus = false; 140 else 141 { 142 matchedSwitch.WithMinus = (s[pos] == kSwitchMinus); 143 if (matchedSwitch.WithMinus) 144 pos++; 145 } 146 break; 147 } 148 case NSwitchType::kPostChar: 149 { 150 if (tailSize < switchForm.MinLen) 151 throw "switch is not full"; 152 UString set = switchForm.PostCharSet; 153 const int kEmptyCharValue = -1; 154 if (tailSize == 0) 155 matchedSwitch.PostCharIndex = kEmptyCharValue; 156 else 157 { 158 int index = set.Find(s[pos]); 159 if (index < 0) 160 matchedSwitch.PostCharIndex = kEmptyCharValue; 161 else 162 { 163 matchedSwitch.PostCharIndex = index; 164 pos++; 165 } 166 } 167 break; 168 } 169 case NSwitchType::kLimitedPostString: 170 case NSwitchType::kUnLimitedPostString: 171 { 172 int minLen = switchForm.MinLen; 173 if (tailSize < minLen) 174 throw "switch is not full"; 175 if (type == NSwitchType::kUnLimitedPostString) 176 { 177 matchedSwitch.PostStrings.Add(s.Mid(pos)); 178 return true; 179 } 180 int maxLen = switchForm.MaxLen; 181 UString stringSwitch = s.Mid(pos, minLen); 182 pos += minLen; 183 for(int i = minLen; i < maxLen && pos < len; i++, pos++) 184 { 185 wchar_t c = s[pos]; 186 if (IsItSwitchChar(c)) 187 break; 188 stringSwitch += c; 189 } 190 matchedSwitch.PostStrings.Add(stringSwitch); 191 break; 192 } 193 case NSwitchType::kSimple: 194 break; 195 } 196 } 197 return true; 198} 199 200const CSwitchResult& CParser::operator[](size_t index) const 201{ 202 return _switches[index]; 203} 204 205///////////////////////////////// 206// Command parsing procedures 207 208int ParseCommand(int numCommandForms, const CCommandForm *commandForms, 209 const UString &commandString, UString &postString) 210{ 211 for(int i = 0; i < numCommandForms; i++) 212 { 213 const UString id = commandForms[i].IDString; 214 if (commandForms[i].PostStringMode) 215 { 216 if(commandString.Find(id) == 0) 217 { 218 postString = commandString.Mid(id.Length()); 219 return i; 220 } 221 } 222 else 223 if (commandString == id) 224 { 225 postString.Empty(); 226 return i; 227 } 228 } 229 return -1; 230} 231 232} 233