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