OSDN Git Service

Add Resolve to explore context menu
[tortoisegit/TortoiseGitJp.git] / src / Utils / CmdLineParser.cpp
1 // TortoiseSVN - a Windows shell extension for easy version control\r
2 \r
3 // Copyright (C) 2003-2006 - Stefan Kueng\r
4 \r
5 // This program is free software; you can redistribute it and/or\r
6 // modify it under the terms of the GNU General Public License\r
7 // as published by the Free Software Foundation; either version 2\r
8 // of the License, or (at your option) any later version.\r
9 \r
10 // This program is distributed in the hope that it will be useful,\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 // GNU General Public License for more details.\r
14 \r
15 // You should have received a copy of the GNU General Public License\r
16 // along with this program; if not, write to the Free Software Foundation,\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
18 //\r
19 #include "stdafx.h"\r
20 #include "CmdLineParser.h"\r
21 #include <locale>\r
22 #include <algorithm>\r
23 \r
24 const TCHAR CCmdLineParser::m_sDelims[] = _T("-/");\r
25 const TCHAR CCmdLineParser::m_sQuotes[] = _T("\"");\r
26 const TCHAR CCmdLineParser::m_sValueSep[] = _T(" :"); // don't forget space!!\r
27 \r
28 \r
29 CCmdLineParser::CCmdLineParser(LPCTSTR sCmdLine)\r
30 {\r
31         if(sCmdLine) \r
32         {\r
33                 Parse(sCmdLine);\r
34         }\r
35 }\r
36 \r
37 CCmdLineParser::~CCmdLineParser()\r
38 {\r
39         m_valueMap.clear();\r
40 }\r
41 \r
42 BOOL CCmdLineParser::Parse(LPCTSTR sCmdLine) \r
43 {\r
44         const stdstring sEmpty = _T("");                        //use this as a value if no actual value is given in commandline\r
45         int nArgs = 0;\r
46 \r
47         if(!sCmdLine) \r
48                 return false;\r
49         \r
50         m_valueMap.clear();\r
51         m_sCmdLine = sCmdLine;\r
52 \r
53         LPCTSTR sCurrent = sCmdLine;\r
54 \r
55         for(;;)\r
56         {\r
57                 //format is  -Key:"arg"\r
58                 \r
59                 if (_tcslen(sCurrent) == 0)\r
60                         break;          // no more data, leave loop\r
61 \r
62                 LPCTSTR sArg = _tcspbrk(sCurrent, m_sDelims);\r
63                 if(!sArg) \r
64                         break; // no (more) delimiters found\r
65                 sArg =  _tcsinc(sArg);\r
66 \r
67                 if(_tcslen(sArg) == 0) \r
68                         break; // ends with delim\r
69                         \r
70                 LPCTSTR sVal = _tcspbrk(sArg, m_sValueSep);\r
71                 if(sVal == NULL) \r
72                 { \r
73                         stdstring Key(sArg);\r
74                         std::transform(Key.begin(), Key.end(), Key.begin(), ::tolower);\r
75                         m_valueMap.insert(CValsMap::value_type(Key, sEmpty));\r
76                         break;\r
77                 } \r
78                 else if (sVal[0] == _T(' ') || _tcslen(sVal) == 1 ) \r
79                 { \r
80                         // cmdline ends with /Key: or a key with no value \r
81                         stdstring Key(sArg, (int)(sVal - sArg));\r
82                         if(!Key.empty()) \r
83                         { \r
84                                 std::transform(Key.begin(), Key.end(), Key.begin(), ::tolower);\r
85                                 m_valueMap.insert(CValsMap::value_type(Key, sEmpty));\r
86                         }\r
87                         sCurrent = _tcsinc(sVal);\r
88                         continue;\r
89                 }\r
90                 else \r
91                 { \r
92                         // key has value\r
93                         stdstring Key(sArg, (int)(sVal - sArg));\r
94                         std::transform(Key.begin(), Key.end(), Key.begin(), ::tolower);\r
95 \r
96                         sVal = _tcsinc(sVal);\r
97 \r
98                         LPCTSTR sQuote = _tcspbrk(sVal, m_sQuotes), sEndQuote(NULL);\r
99                         if(sQuote == sVal) \r
100                         { \r
101                                 // string with quotes (defined in m_sQuotes, e.g. '")\r
102                                 sQuote = _tcsinc(sVal);\r
103                                 sEndQuote = _tcspbrk(sQuote, m_sQuotes);\r
104                         } \r
105                         else \r
106                         {\r
107                                 sQuote = sVal;\r
108                                 sEndQuote = _tcschr(sQuote, _T(' '));\r
109                         }\r
110 \r
111                         if(sEndQuote == NULL) \r
112                         { \r
113                                 // no end quotes or terminating space, take the rest of the string to its end\r
114                                 stdstring csVal(sQuote);\r
115                                 if(!Key.empty()) \r
116                                 { \r
117                                         m_valueMap.insert(CValsMap::value_type(Key, csVal));\r
118                                 }\r
119                                 break;\r
120                         } \r
121                         else \r
122                         { \r
123                                 // end quote\r
124                                 if(!Key.empty()) \r
125                                 {       \r
126                                         stdstring csVal(sQuote, (int)(sEndQuote - sQuote));\r
127                                         m_valueMap.insert(CValsMap::value_type(Key, csVal));\r
128                                 }\r
129                                 sCurrent = _tcsinc(sEndQuote);\r
130                                 continue;\r
131                         }\r
132                 }\r
133         }\r
134         \r
135         return (nArgs > 0);             //TRUE if arguments were found\r
136 }\r
137 \r
138 CCmdLineParser::CValsMap::const_iterator CCmdLineParser::findKey(LPCTSTR sKey) const \r
139 {\r
140         stdstring s(sKey);\r
141         std::transform(s.begin(), s.end(), s.begin(), ::tolower);\r
142         return m_valueMap.find(s);\r
143 }\r
144 \r
145 BOOL CCmdLineParser::HasKey(LPCTSTR sKey) const \r
146 {\r
147         CValsMap::const_iterator it = findKey(sKey);\r
148         if(it == m_valueMap.end()) \r
149                 return false;\r
150         return true;\r
151 }\r
152 \r
153 \r
154 BOOL CCmdLineParser::HasVal(LPCTSTR sKey) const \r
155 {\r
156         CValsMap::const_iterator it = findKey(sKey);\r
157         if(it == m_valueMap.end()) \r
158                 return false;\r
159         if(it->second.empty()) \r
160                 return false;\r
161         return true;\r
162 }\r
163 \r
164 LPCTSTR CCmdLineParser::GetVal(LPCTSTR sKey) const \r
165 {\r
166         CValsMap::const_iterator it = findKey(sKey);\r
167         if (it == m_valueMap.end()) \r
168                 return 0;\r
169         return it->second.c_str();\r
170 }\r
171 \r
172 LONG CCmdLineParser::GetLongVal(LPCTSTR sKey) const\r
173 {\r
174         CValsMap::const_iterator it = findKey(sKey);\r
175         if (it == m_valueMap.end())\r
176                 return 0;\r
177         return _tstol(it->second.c_str());\r
178 }\r
179 \r
180 \r
181 CCmdLineParser::ITERPOS CCmdLineParser::begin() const \r
182 {\r
183         return m_valueMap.begin();\r
184 }\r
185 \r
186 CCmdLineParser::ITERPOS CCmdLineParser::getNext(ITERPOS& pos, stdstring& sKey, stdstring& sValue) const \r
187 {\r
188         if (m_valueMap.end() == pos)\r
189         {\r
190                 sKey.clear();\r
191                 return pos;\r
192         } \r
193         else \r
194         {\r
195                 sKey = pos->first;\r
196                 sValue = pos->second;\r
197                 pos ++;\r
198                 return pos;\r
199         }\r
200 }\r
201 \r
202 BOOL CCmdLineParser::isLast(const ITERPOS& pos) const \r
203 {\r
204         return (pos == m_valueMap.end());\r
205 }\r