Update editorconfig
[TortoiseGit.git] / src / Utils / CmdLineParser.cpp
blob0312a97ace3442a0431d7f9b9e9301e5ae49d7ca
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.
20 #include "stdafx.h"
21 #include "CmdLineParser.h"
22 #include <locale>
23 #include <algorithm>
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)
32 if(sCmdLine)
33 Parse(sCmdLine);
36 CCmdLineParser::~CCmdLineParser()
38 m_valueMap.clear();
41 BOOL CCmdLineParser::Parse(LPCTSTR sCmdLine)
43 const tstring sEmpty = _T(""); //use this as a value if no actual value is given in commandline
44 int nArgs = 0;
46 if(!sCmdLine)
47 return false;
49 m_valueMap.clear();
50 m_sCmdLine = sCmdLine;
52 LPCTSTR sCurrent = sCmdLine;
54 for(;;)
56 //format is -Key:"arg"
58 if (_tcslen(sCurrent) == 0)
59 break; // no more data, leave loop
61 LPCTSTR sArg = _tcspbrk(sCurrent, m_sDelims);
62 if(!sArg)
63 break; // no (more) delimiters found
64 sArg = _tcsinc(sArg);
66 if(_tcslen(sArg) == 0)
67 break; // ends with delim
69 LPCTSTR sVal = _tcspbrk(sArg, m_sValueSep);
70 if (!sVal)
72 tstring Key(sArg);
73 std::transform(Key.begin(), Key.end(), Key.begin(), ::tolower);
74 m_valueMap.insert(CValsMap::value_type(Key, sEmpty));
75 break;
77 else
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(' '))
86 sVal = _tcsinc(sVal);
87 else
89 while (_tcslen(sVal) > 0 && sVal[0] == _T(' '))
90 sVal = _tcsinc(sVal);
93 LPCTSTR nextArg = _tcspbrk(sVal, m_sDelims);
95 sQuote = _tcspbrk(sVal, m_sQuotes);
97 if (nextArg == sVal)
99 // current key has no value, but a next key exist - so don't use next key as value of current one
100 --sVal;
101 sQuote = sVal;
102 sEndQuote = sVal;
104 else if (nextArg && nextArg < sQuote)
106 // current key has a value w/o quotes, but next key one has value in quotes
107 sQuote = sVal;
108 sEndQuote = _tcschr(sQuote, _T(' '));
110 else
112 if(sQuote == sVal)
114 // string with quotes (defined in m_sQuotes, e.g. '")
115 sQuote = _tcsinc(sVal);
116 sEndQuote = _tcspbrk(sQuote, m_sQuotes);
118 else
120 sQuote = sVal;
121 sEndQuote = _tcschr(sQuote, _T(' '));
126 if (!sEndQuote)
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));
134 break;
136 else
138 // end quote
139 if(!Key.empty())
141 tstring csVal(sQuote, (int)(sEndQuote - sQuote));
142 m_valueMap.insert(CValsMap::value_type(Key, csVal));
144 sCurrent = _tcsinc(sEndQuote);
145 continue;
150 return (nArgs > 0); //TRUE if arguments were found
153 CCmdLineParser::CValsMap::const_iterator CCmdLineParser::findKey(LPCTSTR sKey) const
155 tstring s(sKey);
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())
164 return false;
165 return true;
169 BOOL CCmdLineParser::HasVal(LPCTSTR sKey) const
171 CValsMap::const_iterator it = findKey(sKey);
172 if (it == m_valueMap.cend())
173 return false;
174 if(it->second.empty())
175 return false;
176 return true;
179 LPCTSTR CCmdLineParser::GetVal(LPCTSTR sKey) const
181 CValsMap::const_iterator it = findKey(sKey);
182 if (it == m_valueMap.cend())
183 return 0;
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())
191 return 0;
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())
199 return 0;
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)
212 sKey.clear();
213 return pos;
215 else
217 sKey = pos->first;
218 sValue = pos->second;
219 return ++pos;
223 BOOL CCmdLineParser::isLast(const ITERPOS& pos) const
225 return (pos == m_valueMap.cend());