1
// TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2013, 2016-2017 - TortoiseGit
4 // Copyright (C) 2003-2006,2012 - Stefan Kueng
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include "CmdLineParser.h"
25 const TCHAR
CCmdLineParser::m_sDelims
[] = L
"-/";
26 const TCHAR
CCmdLineParser::m_sQuotes
[] = L
"\"";
27 const TCHAR
CCmdLineParser::m_sValueSep
[] = L
" :"; // don't forget space!!
30 CCmdLineParser::CCmdLineParser(LPCTSTR sCmdLine
)
36 CCmdLineParser
& CCmdLineParser::operator=(CCmdLineParser
&& other
)
38 m_sCmdLine
= std::move(other
.m_sCmdLine
);
39 m_valueMap
= std::move(other
.m_valueMap
);
43 BOOL
CCmdLineParser::Parse(LPCTSTR sCmdLine
)
45 const std::wstring sEmpty
; //use this as a value if no actual value is given in commandline
51 m_sCmdLine
= sCmdLine
;
53 tstring working
= sCmdLine
;
54 auto sCurrent
= working
.data();
58 //format is -Key:"arg"
61 break; // no more data, leave loop
63 LPCTSTR sArg
= wcspbrk(sCurrent
, m_sDelims
);
65 break; // no (more) delimiters found
69 break; // ends with delim
71 LPCTSTR sVal
= wcspbrk(sArg
, m_sValueSep
);
74 std::wstring
Key(sArg
);
75 std::transform(Key
.begin(), Key
.end(), Key
.begin(), ::towlower
);
76 m_valueMap
.insert(CValsMap::value_type(Key
, sEmpty
));
81 std::wstring
Key(sArg
, (int)(sVal
- sArg
));
82 std::transform(Key
.begin(), Key
.end(), Key
.begin(), ::towlower
);
84 LPCTSTR
sQuote(nullptr), sEndQuote(nullptr);
91 while (sVal
[0] == L
' ')
95 LPCTSTR nextArg
= wcspbrk(sVal
, m_sDelims
);
97 sQuote
= wcspbrk(sVal
, m_sQuotes
);
101 // current key has no value, but a next key exist - so don't use next key as value of current one
106 else if (nextArg
&& nextArg
< sQuote
)
108 // current key has a value w/o quotes, but next key one has value in quotes
110 sEndQuote
= wcschr(sQuote
, L
' ');
116 // string with quotes (defined in m_sQuotes, e.g. '")
117 sQuote
= _wcsinc(sVal
);
118 sEndQuote
= wcspbrk(sQuote
, m_sQuotes
);
120 // search for double quotes
123 auto nextQuote
= _wcsinc(sEndQuote
);
124 if (nextQuote
[0] == L
'"')
126 working
.erase(working
.begin() + (sEndQuote
- working
.data()));
127 sEndQuote
= wcspbrk(nextQuote
, m_sQuotes
);
136 sEndQuote
= wcschr(sQuote
, L
' ');
143 // no end quotes or terminating space, take the rest of the string to its end
144 if (!Key
.empty() && sQuote
)
146 std::wstring
csVal(sQuote
);
147 m_valueMap
.insert(CValsMap::value_type(Key
, csVal
));
156 std::wstring
csVal(sQuote
, (int)(sEndQuote
- sQuote
));
157 m_valueMap
.insert(CValsMap::value_type(Key
, csVal
));
159 sCurrent
= _wcsinc(sEndQuote
);
165 return !m_valueMap
.empty(); //TRUE if arguments were found
168 CCmdLineParser::CValsMap::const_iterator
CCmdLineParser::findKey(LPCTSTR sKey
) const
170 std::wstring
s(sKey
);
171 std::transform(s
.begin(), s
.end(), s
.begin(), ::towlower
);
172 return m_valueMap
.find(s
);
175 BOOL
CCmdLineParser::HasKey(LPCTSTR sKey
) const
177 CValsMap::const_iterator it
= findKey(sKey
);
178 if (it
== m_valueMap
.cend())
184 BOOL
CCmdLineParser::HasVal(LPCTSTR sKey
) const
186 CValsMap::const_iterator it
= findKey(sKey
);
187 if (it
== m_valueMap
.cend())
189 if(it
->second
.empty())
194 LPCTSTR
CCmdLineParser::GetVal(LPCTSTR sKey
) const
196 CValsMap::const_iterator it
= findKey(sKey
);
197 if (it
== m_valueMap
.cend())
199 return it
->second
.c_str();
202 LONG
CCmdLineParser::GetLongVal(LPCTSTR sKey
) const
204 CValsMap::const_iterator it
= findKey(sKey
);
205 if (it
== m_valueMap
.cend())
207 return _wtol(it
->second
.c_str());
210 __int64
CCmdLineParser::GetLongLongVal(LPCTSTR sKey
) const
212 CValsMap::const_iterator it
= findKey(sKey
);
213 if (it
== m_valueMap
.cend())
215 return _wtoi64(it
->second
.c_str());
218 CCmdLineParser::ITERPOS
CCmdLineParser::begin() const
220 return m_valueMap
.cbegin();
223 CCmdLineParser::ITERPOS
CCmdLineParser::getNext(ITERPOS
& pos
, std::wstring
& sKey
, std::wstring
& sValue
) const
225 if (m_valueMap
.cend() == pos
)
233 sValue
= pos
->second
;
238 BOOL
CCmdLineParser::isLast(const ITERPOS
& pos
) const
240 return (pos
== m_valueMap
.cend());