aboutsummaryrefslogtreecommitdiff
path: root/CPP/Common/CommandLineParser.cpp
diff options
context:
space:
mode:
authorIgor Pavlov <87184205+ip7z@users.noreply.github.com>2021-12-27 00:00:00 +0000
committerIgor Pavlov <87184205+ip7z@users.noreply.github.com>2022-03-18 15:35:13 +0500
commitf19f813537c7aea1c20749c914e756b54a9c3cf5 (patch)
tree816ba62ca7c0fa19f2eb46d9e9d6f7dd7c3a744d /CPP/Common/CommandLineParser.cpp
parent98e06a519b63b81986abe76d28887f6984a7732b (diff)
download7zip-f19f813537c7aea1c20749c914e756b54a9c3cf5.tar.gz
7zip-f19f813537c7aea1c20749c914e756b54a9c3cf5.tar.bz2
7zip-f19f813537c7aea1c20749c914e756b54a9c3cf5.zip
'21.07'21.07
Diffstat (limited to 'CPP/Common/CommandLineParser.cpp')
-rw-r--r--CPP/Common/CommandLineParser.cpp197
1 files changed, 197 insertions, 0 deletions
diff --git a/CPP/Common/CommandLineParser.cpp b/CPP/Common/CommandLineParser.cpp
new file mode 100644
index 0000000..465e0fd
--- /dev/null
+++ b/CPP/Common/CommandLineParser.cpp
@@ -0,0 +1,197 @@
1// CommandLineParser.cpp
2
3#include "StdAfx.h"
4
5#include "CommandLineParser.h"
6
7namespace NCommandLineParser {
8
9bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2)
10{
11 dest1.Empty();
12 dest2.Empty();
13 bool quoteMode = false;
14 unsigned i;
15 for (i = 0; i < src.Len(); i++)
16 {
17 wchar_t c = src[i];
18 if ((c == L' ' || c == L'\t') && !quoteMode)
19 {
20 dest2 = src.Ptr(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
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 if (SplitCommandLine(sTemp, s1, s2))
40 parts.Add(s1);
41 if (s2.IsEmpty())
42 break;
43 sTemp = s2;
44 }
45}
46
47
48static const char * const kStopSwitchParsing = "--";
49
50static bool inline IsItSwitchChar(wchar_t c)
51{
52 return (c == '-');
53}
54
55CParser::CParser():
56 _switches(NULL),
57 StopSwitchIndex(-1)
58{
59}
60
61CParser::~CParser()
62{
63 delete []_switches;
64}
65
66
67// if (s) contains switch then function updates switch structures
68// out: true, if (s) is a switch
69bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms, unsigned numSwitches)
70{
71 if (s.IsEmpty() || !IsItSwitchChar(s[0]))
72 return false;
73
74 unsigned pos = 1;
75 unsigned switchIndex = 0;
76 int maxLen = -1;
77
78 for (unsigned i = 0; i < numSwitches; i++)
79 {
80 const char * const key = switchForms[i].Key;
81 unsigned switchLen = MyStringLen(key);
82 if ((int)switchLen <= maxLen || pos + switchLen > s.Len())
83 continue;
84 if (IsString1PrefixedByString2_NoCase_Ascii((const wchar_t *)s + pos, key))
85 {
86 switchIndex = i;
87 maxLen = (int)switchLen;
88 }
89 }
90
91 if (maxLen < 0)
92 {
93 ErrorMessage = "Unknown switch:";
94 return false;
95 }
96
97 pos += (unsigned)maxLen;
98
99 CSwitchResult &sw = _switches[switchIndex];
100 const CSwitchForm &form = switchForms[switchIndex];
101
102 if (!form.Multi && sw.ThereIs)
103 {
104 ErrorMessage = "Multiple instances for switch:";
105 return false;
106 }
107
108 sw.ThereIs = true;
109
110 const unsigned rem = s.Len() - pos;
111 if (rem < form.MinLen)
112 {
113 ErrorMessage = "Too short switch:";
114 return false;
115 }
116
117 sw.WithMinus = false;
118 sw.PostCharIndex = -1;
119
120 switch (form.Type)
121 {
122 case NSwitchType::kMinus:
123 if (rem == 1)
124 {
125 sw.WithMinus = (s[pos] == '-');
126 if (sw.WithMinus)
127 return true;
128 ErrorMessage = "Incorrect switch postfix:";
129 return false;
130 }
131 break;
132
133 case NSwitchType::kChar:
134 if (rem == 1)
135 {
136 wchar_t c = s[pos];
137 if (c <= 0x7F)
138 {
139 sw.PostCharIndex = FindCharPosInString(form.PostCharSet, (char)c);
140 if (sw.PostCharIndex >= 0)
141 return true;
142 }
143 ErrorMessage = "Incorrect switch postfix:";
144 return false;
145 }
146 break;
147
148 case NSwitchType::kString:
149 {
150 sw.PostStrings.Add(s.Ptr(pos));
151 return true;
152 }
153 }
154
155 if (pos != s.Len())
156 {
157 ErrorMessage = "Too long switch:";
158 return false;
159 }
160 return true;
161}
162
163
164bool CParser::ParseStrings(const CSwitchForm *switchForms, unsigned numSwitches, const UStringVector &commandStrings)
165{
166 StopSwitchIndex = -1;
167 ErrorMessage.Empty();
168 ErrorLine.Empty();
169 NonSwitchStrings.Clear();
170 delete []_switches;
171 _switches = NULL;
172 _switches = new CSwitchResult[numSwitches];
173
174 FOR_VECTOR (i, commandStrings)
175 {
176 const UString &s = commandStrings[i];
177 if (StopSwitchIndex < 0)
178 {
179 if (s.IsEqualTo(kStopSwitchParsing))
180 {
181 StopSwitchIndex = (int)NonSwitchStrings.Size();
182 continue;
183 }
184 if (!s.IsEmpty() && IsItSwitchChar(s[0]))
185 {
186 if (ParseString(s, switchForms, numSwitches))
187 continue;
188 ErrorLine = s;
189 return false;
190 }
191 }
192 NonSwitchStrings.Add(s);
193 }
194 return true;
195}
196
197}