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