*.js files: keep the style consistent
[TortoiseGit.git] / src / Utils / CmdLineParser.cpp
blobfd7da6b9685fa6a52e350dee1e9cb1da75eaf275
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2013 - TortoiseGit
4 // Copyright (C) 2003-2006 - 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)
34 Parse(sCmdLine);
38 CCmdLineParser::~CCmdLineParser()
40 m_valueMap.clear();
43 BOOL CCmdLineParser::Parse(LPCTSTR sCmdLine)
45 const stdstring sEmpty = _T(""); //use this as a value if no actual value is given in commandline
46 int nArgs = 0;
48 if(!sCmdLine)
49 return false;
51 m_valueMap.clear();
52 m_sCmdLine = sCmdLine;
54 LPCTSTR sCurrent = sCmdLine;
56 for(;;)
58 //format is -Key:"arg"
60 if (_tcslen(sCurrent) == 0)
61 break; // no more data, leave loop
63 LPCTSTR sArg = _tcspbrk(sCurrent, m_sDelims);
64 if(!sArg)
65 break; // no (more) delimiters found
66 sArg = _tcsinc(sArg);
68 if(_tcslen(sArg) == 0)
69 break; // ends with delim
71 LPCTSTR sVal = _tcspbrk(sArg, m_sValueSep);
72 if(sVal == NULL)
74 stdstring Key(sArg);
75 std::transform(Key.begin(), Key.end(), Key.begin(), ::tolower);
76 m_valueMap.insert(CValsMap::value_type(Key, sEmpty));
77 break;
79 else
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(' '))
88 sVal = _tcsinc(sVal);
89 else
91 while (_tcslen(sVal) > 0 && sVal[0] == _T(' '))
92 sVal = _tcsinc(sVal);
95 LPCTSTR nextArg = _tcspbrk(sVal, m_sDelims);
97 sQuote = _tcspbrk(sVal, m_sQuotes);
99 if (nextArg == sVal)
101 // current key has no value, but a next key exist - so don't use next key as value of current one
102 --sVal;
103 sQuote = sVal;
104 sEndQuote = sVal;
106 else if (nextArg != NULL && nextArg < sQuote)
108 // current key has a value w/o quotes, but next key one has value in quotes
109 sQuote = sVal;
110 sEndQuote = _tcschr(sQuote, _T(' '));
112 else
114 if(sQuote == sVal)
116 // string with quotes (defined in m_sQuotes, e.g. '")
117 sQuote = _tcsinc(sVal);
118 sEndQuote = _tcspbrk(sQuote, m_sQuotes);
120 else
122 sQuote = sVal;
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 stdstring csVal(sQuote);
132 if(!Key.empty())
134 m_valueMap.insert(CValsMap::value_type(Key, csVal));
136 break;
138 else
140 // end quote
141 if(!Key.empty())
143 stdstring csVal(sQuote, (int)(sEndQuote - sQuote));
144 m_valueMap.insert(CValsMap::value_type(Key, csVal));
146 sCurrent = _tcsinc(sEndQuote);
147 continue;
152 return (nArgs > 0); //TRUE if arguments were found
155 CCmdLineParser::CValsMap::const_iterator CCmdLineParser::findKey(LPCTSTR sKey) const
157 stdstring s(sKey);
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())
166 return false;
167 return true;
171 BOOL CCmdLineParser::HasVal(LPCTSTR sKey) const
173 CValsMap::const_iterator it = findKey(sKey);
174 if(it == m_valueMap.end())
175 return false;
176 if(it->second.empty())
177 return false;
178 return true;
181 LPCTSTR CCmdLineParser::GetVal(LPCTSTR sKey) const
183 CValsMap::const_iterator it = findKey(sKey);
184 if (it == m_valueMap.end())
185 return 0;
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())
193 return 0;
194 return _tstol(it->second.c_str());
198 CCmdLineParser::ITERPOS CCmdLineParser::begin() const
200 return m_valueMap.begin();
203 CCmdLineParser::ITERPOS CCmdLineParser::getNext(ITERPOS& pos, stdstring& sKey, stdstring& sValue) const
205 if (m_valueMap.end() == pos)
207 sKey.clear();
208 return pos;
210 else
212 sKey = pos->first;
213 sValue = pos->second;
214 return ++pos;
218 BOOL CCmdLineParser::isLast(const ITERPOS& pos) const
220 return (pos == m_valueMap.end());