1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2013 - 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
)
38 CCmdLineParser::~CCmdLineParser()
43 BOOL
CCmdLineParser::Parse(LPCTSTR sCmdLine
)
45 const stdstring sEmpty
= _T(""); //use this as a value if no actual value is given in commandline
52 m_sCmdLine
= sCmdLine
;
54 LPCTSTR sCurrent
= sCmdLine
;
58 //format is -Key:"arg"
60 if (_tcslen(sCurrent
) == 0)
61 break; // no more data, leave loop
63 LPCTSTR sArg
= _tcspbrk(sCurrent
, m_sDelims
);
65 break; // no (more) delimiters found
68 if(_tcslen(sArg
) == 0)
69 break; // ends with delim
71 LPCTSTR sVal
= _tcspbrk(sArg
, m_sValueSep
);
75 std::transform(Key
.begin(), Key
.end(), Key
.begin(), ::tolower
);
76 m_valueMap
.insert(CValsMap::value_type(Key
, sEmpty
));
81 stdstring
Key(sArg
, (int)(sVal
- sArg
));
82 std::transform(Key
.begin(), Key
.end(), Key
.begin(), ::tolower
);
84 LPCTSTR
sQuote(NULL
), sEndQuote(NULL
);
85 if (_tcslen(sVal
) > 0)
87 if (sVal
[0] != _T(' '))
91 while (_tcslen(sVal
) > 0 && sVal
[0] == _T(' '))
95 LPCTSTR nextArg
= _tcspbrk(sVal
, m_sDelims
);
97 sQuote
= _tcspbrk(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
!= NULL
&& nextArg
< sQuote
)
108 // current key has a value w/o quotes, but next key one has value in quotes
110 sEndQuote
= _tcschr(sQuote
, _T(' '));
116 // string with quotes (defined in m_sQuotes, e.g. '")
117 sQuote
= _tcsinc(sVal
);
118 sEndQuote
= _tcspbrk(sQuote
, m_sQuotes
);
123 sEndQuote
= _tcschr(sQuote
, _T(' '));
128 if(sEndQuote
== NULL
)
130 // no end quotes or terminating space, take the rest of the string to its end
131 if (!Key
.empty() && sQuote
)
133 stdstring
csVal(sQuote
);
134 m_valueMap
.insert(CValsMap::value_type(Key
, csVal
));
143 stdstring
csVal(sQuote
, (int)(sEndQuote
- sQuote
));
144 m_valueMap
.insert(CValsMap::value_type(Key
, csVal
));
146 sCurrent
= _tcsinc(sEndQuote
);
152 return (nArgs
> 0); //TRUE if arguments were found
155 CCmdLineParser::CValsMap::const_iterator
CCmdLineParser::findKey(LPCTSTR sKey
) const
158 std::transform(s
.begin(), s
.end(), s
.begin(), ::tolower
);
159 return m_valueMap
.find(s
);
162 BOOL
CCmdLineParser::HasKey(LPCTSTR sKey
) const
164 CValsMap::const_iterator it
= findKey(sKey
);
165 if(it
== m_valueMap
.end())
171 BOOL
CCmdLineParser::HasVal(LPCTSTR sKey
) const
173 CValsMap::const_iterator it
= findKey(sKey
);
174 if(it
== m_valueMap
.end())
176 if(it
->second
.empty())
181 LPCTSTR
CCmdLineParser::GetVal(LPCTSTR sKey
) const
183 CValsMap::const_iterator it
= findKey(sKey
);
184 if (it
== m_valueMap
.end())
186 return it
->second
.c_str();
189 LONG
CCmdLineParser::GetLongVal(LPCTSTR sKey
) const
191 CValsMap::const_iterator it
= findKey(sKey
);
192 if (it
== m_valueMap
.end())
194 return _tstol(it
->second
.c_str());
197 __int64
CCmdLineParser::GetLongLongVal(LPCTSTR sKey
) const
199 CValsMap::const_iterator it
= findKey(sKey
);
200 if (it
== m_valueMap
.end())
202 return _ttoi64(it
->second
.c_str());
205 CCmdLineParser::ITERPOS
CCmdLineParser::begin() const
207 return m_valueMap
.begin();
210 CCmdLineParser::ITERPOS
CCmdLineParser::getNext(ITERPOS
& pos
, stdstring
& sKey
, stdstring
& sValue
) const
212 if (m_valueMap
.end() == pos
)
220 sValue
= pos
->second
;
225 BOOL
CCmdLineParser::isLast(const ITERPOS
& pos
) const
227 return (pos
== m_valueMap
.end());