1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2013, 2016 - 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
[] = _T("-/");
26 const TCHAR
CCmdLineParser::m_sQuotes
[] = _T("\"");
27 const TCHAR
CCmdLineParser::m_sValueSep
[] = _T(" :"); // don't forget space!!
30 CCmdLineParser::CCmdLineParser(LPCTSTR sCmdLine
)
36 CCmdLineParser::~CCmdLineParser()
41 BOOL
CCmdLineParser::Parse(LPCTSTR sCmdLine
)
43 const tstring sEmpty
= _T(""); //use this as a value if no actual value is given in commandline
50 m_sCmdLine
= sCmdLine
;
52 LPCTSTR sCurrent
= sCmdLine
;
56 //format is -Key:"arg"
58 if (_tcslen(sCurrent
) == 0)
59 break; // no more data, leave loop
61 LPCTSTR sArg
= _tcspbrk(sCurrent
, m_sDelims
);
63 break; // no (more) delimiters found
66 if(_tcslen(sArg
) == 0)
67 break; // ends with delim
69 LPCTSTR sVal
= _tcspbrk(sArg
, m_sValueSep
);
73 std::transform(Key
.begin(), Key
.end(), Key
.begin(), ::tolower
);
74 m_valueMap
.insert(CValsMap::value_type(Key
, sEmpty
));
79 tstring
Key(sArg
, (int)(sVal
- sArg
));
80 std::transform(Key
.begin(), Key
.end(), Key
.begin(), ::tolower
);
82 LPCTSTR
sQuote(nullptr), sEndQuote(nullptr);
83 if (_tcslen(sVal
) > 0)
85 if (sVal
[0] != _T(' '))
89 while (_tcslen(sVal
) > 0 && sVal
[0] == _T(' '))
93 LPCTSTR nextArg
= _tcspbrk(sVal
, m_sDelims
);
95 sQuote
= _tcspbrk(sVal
, m_sQuotes
);
99 // current key has no value, but a next key exist - so don't use next key as value of current one
104 else if (nextArg
&& nextArg
< sQuote
)
106 // current key has a value w/o quotes, but next key one has value in quotes
108 sEndQuote
= _tcschr(sQuote
, _T(' '));
114 // string with quotes (defined in m_sQuotes, e.g. '")
115 sQuote
= _tcsinc(sVal
);
116 sEndQuote
= _tcspbrk(sQuote
, m_sQuotes
);
121 sEndQuote
= _tcschr(sQuote
, _T(' '));
128 // no end quotes or terminating space, take the rest of the string to its end
129 if (!Key
.empty() && sQuote
)
131 tstring
csVal(sQuote
);
132 m_valueMap
.insert(CValsMap::value_type(Key
, csVal
));
141 tstring
csVal(sQuote
, (int)(sEndQuote
- sQuote
));
142 m_valueMap
.insert(CValsMap::value_type(Key
, csVal
));
144 sCurrent
= _tcsinc(sEndQuote
);
150 return (nArgs
> 0); //TRUE if arguments were found
153 CCmdLineParser::CValsMap::const_iterator
CCmdLineParser::findKey(LPCTSTR sKey
) const
156 std::transform(s
.begin(), s
.end(), s
.begin(), ::tolower
);
157 return m_valueMap
.find(s
);
160 BOOL
CCmdLineParser::HasKey(LPCTSTR sKey
) const
162 CValsMap::const_iterator it
= findKey(sKey
);
163 if (it
== m_valueMap
.cend())
169 BOOL
CCmdLineParser::HasVal(LPCTSTR sKey
) const
171 CValsMap::const_iterator it
= findKey(sKey
);
172 if (it
== m_valueMap
.cend())
174 if(it
->second
.empty())
179 LPCTSTR
CCmdLineParser::GetVal(LPCTSTR sKey
) const
181 CValsMap::const_iterator it
= findKey(sKey
);
182 if (it
== m_valueMap
.cend())
184 return it
->second
.c_str();
187 LONG
CCmdLineParser::GetLongVal(LPCTSTR sKey
) const
189 CValsMap::const_iterator it
= findKey(sKey
);
190 if (it
== m_valueMap
.cend())
192 return _tstol(it
->second
.c_str());
195 __int64
CCmdLineParser::GetLongLongVal(LPCTSTR sKey
) const
197 CValsMap::const_iterator it
= findKey(sKey
);
198 if (it
== m_valueMap
.cend())
200 return _ttoi64(it
->second
.c_str());
203 CCmdLineParser::ITERPOS
CCmdLineParser::begin() const
205 return m_valueMap
.cbegin();
208 CCmdLineParser::ITERPOS
CCmdLineParser::getNext(ITERPOS
& pos
, tstring
& sKey
, tstring
& sValue
) const
210 if (m_valueMap
.cend() == pos
)
218 sValue
= pos
->second
;
223 BOOL
CCmdLineParser::isLast(const ITERPOS
& pos
) const
225 return (pos
== m_valueMap
.cend());