Filenames in FILE_NOTIFY_INFORMATION are not null terminated, so don't use _TRUNCATE...
[TortoiseGit.git] / src / Utils / CmdLineParser.cpp
blobd3ac545a8446bb4b688de288be1e58957b741217
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2006 - Stefan Kueng
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include "stdafx.h"
20 #include "CmdLineParser.h"
21 #include <locale>
22 #include <algorithm>
24 const TCHAR CCmdLineParser::m_sDelims[] = _T("-/");
25 const TCHAR CCmdLineParser::m_sQuotes[] = _T("\"");
26 const TCHAR CCmdLineParser::m_sValueSep[] = _T(" :"); // don't forget space!!
29 CCmdLineParser::CCmdLineParser(LPCTSTR sCmdLine)
31 if(sCmdLine)
33 Parse(sCmdLine);
37 CCmdLineParser::~CCmdLineParser()
39 m_valueMap.clear();
42 BOOL CCmdLineParser::Parse(LPCTSTR sCmdLine)
44 const stdstring sEmpty = _T(""); //use this as a value if no actual value is given in commandline
45 int nArgs = 0;
47 if(!sCmdLine)
48 return false;
50 m_valueMap.clear();
51 m_sCmdLine = sCmdLine;
53 LPCTSTR sCurrent = sCmdLine;
55 for(;;)
57 //format is -Key:"arg"
59 if (_tcslen(sCurrent) == 0)
60 break; // no more data, leave loop
62 LPCTSTR sArg = _tcspbrk(sCurrent, m_sDelims);
63 if(!sArg)
64 break; // no (more) delimiters found
65 sArg = _tcsinc(sArg);
67 if(_tcslen(sArg) == 0)
68 break; // ends with delim
70 LPCTSTR sVal = _tcspbrk(sArg, m_sValueSep);
71 if(sVal == NULL)
73 stdstring Key(sArg);
74 std::transform(Key.begin(), Key.end(), Key.begin(), ::tolower);
75 m_valueMap.insert(CValsMap::value_type(Key, sEmpty));
76 break;
78 else if (sVal[0] == _T(' ') || _tcslen(sVal) == 1 )
80 // cmdline ends with /Key: or a key with no value
81 stdstring Key(sArg, (int)(sVal - sArg));
82 if(!Key.empty())
84 std::transform(Key.begin(), Key.end(), Key.begin(), ::tolower);
85 m_valueMap.insert(CValsMap::value_type(Key, sEmpty));
87 sCurrent = _tcsinc(sVal);
88 continue;
90 else
92 // key has value
93 stdstring Key(sArg, (int)(sVal - sArg));
94 std::transform(Key.begin(), Key.end(), Key.begin(), ::tolower);
96 sVal = _tcsinc(sVal);
98 LPCTSTR sQuote = _tcspbrk(sVal, m_sQuotes), sEndQuote(NULL);
99 if(sQuote == sVal)
101 // string with quotes (defined in m_sQuotes, e.g. '")
102 sQuote = _tcsinc(sVal);
103 sEndQuote = _tcspbrk(sQuote, m_sQuotes);
105 else
107 sQuote = sVal;
108 sEndQuote = _tcschr(sQuote, _T(' '));
111 if(sEndQuote == NULL)
113 // no end quotes or terminating space, take the rest of the string to its end
114 stdstring csVal(sQuote);
115 if(!Key.empty())
117 m_valueMap.insert(CValsMap::value_type(Key, csVal));
119 break;
121 else
123 // end quote
124 if(!Key.empty())
126 stdstring csVal(sQuote, (int)(sEndQuote - sQuote));
127 m_valueMap.insert(CValsMap::value_type(Key, csVal));
129 sCurrent = _tcsinc(sEndQuote);
130 continue;
135 return (nArgs > 0); //TRUE if arguments were found
138 CCmdLineParser::CValsMap::const_iterator CCmdLineParser::findKey(LPCTSTR sKey) const
140 stdstring s(sKey);
141 std::transform(s.begin(), s.end(), s.begin(), ::tolower);
142 return m_valueMap.find(s);
145 BOOL CCmdLineParser::HasKey(LPCTSTR sKey) const
147 CValsMap::const_iterator it = findKey(sKey);
148 if(it == m_valueMap.end())
149 return false;
150 return true;
154 BOOL CCmdLineParser::HasVal(LPCTSTR sKey) const
156 CValsMap::const_iterator it = findKey(sKey);
157 if(it == m_valueMap.end())
158 return false;
159 if(it->second.empty())
160 return false;
161 return true;
164 LPCTSTR CCmdLineParser::GetVal(LPCTSTR sKey) const
166 CValsMap::const_iterator it = findKey(sKey);
167 if (it == m_valueMap.end())
168 return 0;
169 return it->second.c_str();
172 LONG CCmdLineParser::GetLongVal(LPCTSTR sKey) const
174 CValsMap::const_iterator it = findKey(sKey);
175 if (it == m_valueMap.end())
176 return 0;
177 return _tstol(it->second.c_str());
181 CCmdLineParser::ITERPOS CCmdLineParser::begin() const
183 return m_valueMap.begin();
186 CCmdLineParser::ITERPOS CCmdLineParser::getNext(ITERPOS& pos, stdstring& sKey, stdstring& sValue) const
188 if (m_valueMap.end() == pos)
190 sKey.clear();
191 return pos;
193 else
195 sKey = pos->first;
196 sValue = pos->second;
197 pos ++;
198 return pos;
202 BOOL CCmdLineParser::isLast(const ITERPOS& pos) const
204 return (pos == m_valueMap.end());