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