Upload 2.0.2
[physicsfs] / lzma / CS / 7zip / Common / CommandLineParser.cs
1 // CommandLineParser.cs
2
3 using System;
4 using System.Collections;
5
6 namespace SevenZip.CommandLineParser
7 {
8         public enum SwitchType
9         {
10                 Simple,
11                 PostMinus,
12                 LimitedPostString,
13                 UnLimitedPostString,
14                 PostChar
15         }
16
17         public class SwitchForm
18         {
19                 public string IDString;
20                 public SwitchType Type;
21                 public bool Multi;
22                 public int MinLen;
23                 public int MaxLen;
24                 public string PostCharSet;
25
26                 public SwitchForm(string idString, SwitchType type, bool multi,
27                         int minLen, int maxLen, string postCharSet)
28                 {
29                         IDString = idString;
30                         Type = type;
31                         Multi = multi;
32                         MinLen = minLen;
33                         MaxLen = maxLen;
34                         PostCharSet = postCharSet;
35                 }
36                 public SwitchForm(string idString, SwitchType type, bool multi, int minLen):
37                         this(idString, type, multi, minLen, 0, "")
38                 {
39                 }
40                 public SwitchForm(string idString, SwitchType type, bool multi):
41                         this(idString, type, multi, 0)
42                 {
43                 }
44         }
45
46         public class SwitchResult
47         {
48                 public bool ThereIs;
49                 public bool WithMinus;
50                 public ArrayList PostStrings = new ArrayList();
51                 public int PostCharIndex;
52                 public SwitchResult()
53                 {
54                         ThereIs = false;
55                 }
56         }
57
58         public class Parser
59         {
60                 public ArrayList NonSwitchStrings = new ArrayList();
61                 SwitchResult[] _switches;
62
63                 public Parser(int numSwitches)
64                 {
65                         _switches = new SwitchResult[numSwitches];
66                         for (int i = 0; i < numSwitches; i++)
67                                 _switches[i] = new SwitchResult();
68                 }
69
70                 bool ParseString(string srcString, SwitchForm[] switchForms)
71                 {
72                         int len = srcString.Length;
73                         if (len == 0)
74                                 return false;
75                         int pos = 0;
76                         if (!IsItSwitchChar(srcString[pos]))
77                                 return false;
78                         while (pos < len)
79                         {
80                                 if (IsItSwitchChar(srcString[pos]))
81                                         pos++;
82                                 const int kNoLen = -1;
83                                 int matchedSwitchIndex = 0;
84                                 int maxLen = kNoLen;
85                                 for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++)
86                                 {
87                                         int switchLen = switchForms[switchIndex].IDString.Length;
88                                         if (switchLen <= maxLen || pos + switchLen > len)
89                                                 continue;
90                                         if (String.Compare(switchForms[switchIndex].IDString, 0,
91                                                         srcString, pos, switchLen, true) == 0)
92                                         {
93                                                 matchedSwitchIndex = switchIndex;
94                                                 maxLen = switchLen;
95                                         }
96                                 }
97                                 if (maxLen == kNoLen)
98                                         throw new Exception("maxLen == kNoLen");
99                                 SwitchResult matchedSwitch = _switches[matchedSwitchIndex];
100                                 SwitchForm switchForm = switchForms[matchedSwitchIndex];
101                                 if ((!switchForm.Multi) && matchedSwitch.ThereIs)
102                                         throw new Exception("switch must be single");
103                                 matchedSwitch.ThereIs = true;
104                                 pos += maxLen;
105                                 int tailSize = len - pos;
106                                 SwitchType type = switchForm.Type;
107                                 switch (type)
108                                 {
109                                         case SwitchType.PostMinus:
110                                                 {
111                                                         if (tailSize == 0)
112                                                                 matchedSwitch.WithMinus = false;
113                                                         else
114                                                         {
115                                                                 matchedSwitch.WithMinus = (srcString[pos] == kSwitchMinus);
116                                                                 if (matchedSwitch.WithMinus)
117                                                                         pos++;
118                                                         }
119                                                         break;
120                                                 }
121                                         case SwitchType.PostChar:
122                                                 {
123                                                         if (tailSize < switchForm.MinLen)
124                                                                 throw new Exception("switch is not full");
125                                                         string charSet = switchForm.PostCharSet;
126                                                         const int kEmptyCharValue = -1;
127                                                         if (tailSize == 0)
128                                                                 matchedSwitch.PostCharIndex = kEmptyCharValue;
129                                                         else
130                                                         {
131                                                                 int index = charSet.IndexOf(srcString[pos]);
132                                                                 if (index < 0)
133                                                                         matchedSwitch.PostCharIndex = kEmptyCharValue;
134                                                                 else
135                                                                 {
136                                                                         matchedSwitch.PostCharIndex = index;
137                                                                         pos++;
138                                                                 }
139                                                         }
140                                                         break;
141                                                 }
142                                         case SwitchType.LimitedPostString:
143                                         case SwitchType.UnLimitedPostString:
144                                                 {
145                                                         int minLen = switchForm.MinLen;
146                                                         if (tailSize < minLen)
147                                                                 throw new Exception("switch is not full");
148                                                         if (type == SwitchType.UnLimitedPostString)
149                                                         {
150                                                                 matchedSwitch.PostStrings.Add(srcString.Substring(pos));
151                                                                 return true;
152                                                         }
153                                                         String stringSwitch = srcString.Substring(pos, minLen);
154                                                         pos += minLen;
155                                                         for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++)
156                                                         {
157                                                                 char c = srcString[pos];
158                                                                 if (IsItSwitchChar(c))
159                                                                         break;
160                                                                 stringSwitch += c;
161                                                         }
162                                                         matchedSwitch.PostStrings.Add(stringSwitch);
163                                                         break;
164                                                 }
165                                 }
166                         }
167                         return true;
168
169                 }
170
171                 public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings)
172                 {
173                         int numCommandStrings = commandStrings.Length;
174                         bool stopSwitch = false;
175                         for (int i = 0; i < numCommandStrings; i++)
176                         {
177                                 string s = commandStrings[i];
178                                 if (stopSwitch)
179                                         NonSwitchStrings.Add(s);
180                                 else
181                                         if (s == kStopSwitchParsing)
182                                         stopSwitch = true;
183                                 else
184                                         if (!ParseString(s, switchForms))
185                                         NonSwitchStrings.Add(s);
186                         }
187                 }
188
189                 public SwitchResult this[int index] { get { return _switches[index]; } }
190
191                 public static int ParseCommand(CommandForm[] commandForms, string commandString,
192                         out string postString)
193                 {
194                         for (int i = 0; i < commandForms.Length; i++)
195                         {
196                                 string id = commandForms[i].IDString;
197                                 if (commandForms[i].PostStringMode)
198                                 {
199                                         if (commandString.IndexOf(id) == 0)
200                                         {
201                                                 postString = commandString.Substring(id.Length);
202                                                 return i;
203                                         }
204                                 }
205                                 else
206                                         if (commandString == id)
207                                 {
208                                         postString = "";
209                                         return i;
210                                 }
211                         }
212                         postString = "";
213                         return -1;
214                 }
215
216                 static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms,
217                         string commandString, ArrayList indices)
218                 {
219                         indices.Clear();
220                         int numUsedChars = 0;
221                         for (int i = 0; i < numForms; i++)
222                         {
223                                 CommandSubCharsSet charsSet = forms[i];
224                                 int currentIndex = -1;
225                                 int len = charsSet.Chars.Length;
226                                 for (int j = 0; j < len; j++)
227                                 {
228                                         char c = charsSet.Chars[j];
229                                         int newIndex = commandString.IndexOf(c);
230                                         if (newIndex >= 0)
231                                         {
232                                                 if (currentIndex >= 0)
233                                                         return false;
234                                                 if (commandString.IndexOf(c, newIndex + 1) >= 0)
235                                                         return false;
236                                                 currentIndex = j;
237                                                 numUsedChars++;
238                                         }
239                                 }
240                                 if (currentIndex == -1 && !charsSet.EmptyAllowed)
241                                         return false;
242                                 indices.Add(currentIndex);
243                         }
244                         return (numUsedChars == commandString.Length);
245                 }
246                 const char kSwitchID1 = '-';
247                 const char kSwitchID2 = '/';
248
249                 const char kSwitchMinus = '-';
250                 const string kStopSwitchParsing = "--";
251
252                 static bool IsItSwitchChar(char c)
253                 {
254                         return (c == kSwitchID1 || c == kSwitchID2);
255                 }
256         }
257
258         public class CommandForm
259         {
260                 public string IDString = "";
261                 public bool PostStringMode = false;
262                 public CommandForm(string idString, bool postStringMode)
263                 {
264                         IDString = idString;
265                         PostStringMode = postStringMode;
266                 }
267         }
268
269         class CommandSubCharsSet
270         {
271                 public string Chars = "";
272                 public bool EmptyAllowed = false;
273         }
274 }