1 //===-- MICmdArgValString.cpp -----------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 // File: MICmdArgValString.cpp
13 // Overview: CMICmdArgValString implementation.
15 // Environment: Compilers: Visual C++ 12.
16 // gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
17 // Libraries: See MIReadmetxt.
23 #include "MICmdArgValString.h"
24 #include "MICmdArgContext.h"
26 //++ ------------------------------------------------------------------------------------
27 // Details: CMICmdArgValString constructor.
33 CMICmdArgValString::CMICmdArgValString(void)
34 : m_bHandleQuotedString(false)
35 , m_bAcceptNumbers(false)
36 , m_bHandleDirPaths(false)
37 , m_bHandleAnything(false)
41 //++ ------------------------------------------------------------------------------------
42 // Details: CMICmdArgValString constructor.
44 // Args: vbAnything - (R) True = Parse a string and accept anything, false = do not accept anything.
48 CMICmdArgValString::CMICmdArgValString(const bool vbAnything)
49 : m_bHandleQuotedString(false)
50 , m_bAcceptNumbers(false)
51 , m_bHandleDirPaths(false)
52 , m_bHandleAnything(vbAnything)
56 //++ ------------------------------------------------------------------------------------
57 // Details: CMICmdArgValString constructor.
59 // Args: vbHandleQuotes - (R) True = Parse a string surrounded by quotes spaces are not delimitors, false = only text up to
60 // next delimiting space character.
61 // vbAcceptNumbers - (R) True = Parse a string and accept as a number if number, false = numbers not recognised
63 // vbHandleDirPaths - (R) True = Parse a string and accept as a file path if a path, false = file paths are not
64 // recognised as string types.
68 CMICmdArgValString::CMICmdArgValString(const bool vbHandleQuotes, const bool vbAcceptNumbers, const bool vbHandleDirPaths)
69 : m_bHandleQuotedString(vbHandleQuotes)
70 , m_bAcceptNumbers(vbAcceptNumbers)
71 , m_bHandleDirPaths(vbHandleDirPaths)
72 , m_bHandleAnything(false)
76 //++ ------------------------------------------------------------------------------------
77 // Details: CMICmdArgValString constructor.
79 // Args: vrArgName - (R) Argument's name to search by.
80 // vbMandatory - (R) True = Yes must be present, false = optional argument.
81 // vbHandleByCmd - (R) True = Command processes *this option, false = not handled.
82 // vbHandleQuotes - (R) True = Parse a string surrounded by quotes spaces are not delimitors, false = only text up to
83 // next delimiting space character. (Dflt = false)
84 // vbAcceptNumbers - (R) True = Parse a string and accept as a number if number, false = numbers not recognised as
85 // string types. (Dflt = false)
89 CMICmdArgValString::CMICmdArgValString(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd,
90 const bool vbHandleQuotes /* = false */, const bool vbAcceptNumbers /* = false */)
91 : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd)
92 , m_bHandleQuotedString(vbHandleQuotes)
93 , m_bAcceptNumbers(vbAcceptNumbers)
94 , m_bHandleDirPaths(false)
95 , m_bHandleAnything(false)
99 //++ ------------------------------------------------------------------------------------
100 // Details: CMICmdArgValString destructor.
106 CMICmdArgValString::~CMICmdArgValString(void)
110 //++ ------------------------------------------------------------------------------------
111 // Details: Parse the command's argument options string and try to extract the value *this
112 // argument is looking for.
114 // Args: vrwArgContext - (RW) The command's argument options string.
115 // Return: MIstatus::success - Functional succeeded.
116 // MIstatus::failure - Functional failed.
120 CMICmdArgValString::Validate(CMICmdArgContext &vrwArgContext)
122 if (vrwArgContext.IsEmpty())
123 return MIstatus::success;
125 if (m_bHandleQuotedString)
126 return (ValidateQuotedText(vrwArgContext) || ValidateQuotedTextEmbedded(vrwArgContext));
128 return ValidateSingleText(vrwArgContext);
131 //++ ------------------------------------------------------------------------------------
132 // Details: Parse the command's argument options string and try to extract only the next
133 // word delimited by the next space.
135 // Args: vrwArgContext - (RW) The command's argument options string.
136 // Return: MIstatus::success - Functional succeeded.
137 // MIstatus::failure - Functional failed.
141 CMICmdArgValString::ValidateSingleText(CMICmdArgContext &vrwArgContext)
143 if (vrwArgContext.GetNumberArgsPresent() == 1)
145 const CMIUtilString &rArg(vrwArgContext.GetArgsLeftToParse());
146 if (IsStringArg(rArg))
151 vrwArgContext.RemoveArg(rArg);
152 return MIstatus::success;
155 return MIstatus::failure;
158 // More than one option...
159 const CMIUtilString::VecString_t vecOptions(vrwArgContext.GetArgs());
160 CMIUtilString::VecString_t::const_iterator it = vecOptions.begin();
161 while (it != vecOptions.end())
163 const CMIUtilString &rArg(*it);
164 if (IsStringArg(rArg))
168 if (vrwArgContext.RemoveArg(rArg))
172 return MIstatus::success;
175 return MIstatus::failure;
182 return MIstatus::failure;
185 //++ ------------------------------------------------------------------------------------
186 // Details: Parse the command's argument options string and try to extract all the words
187 // between quotes then delimited by the next space. Can fall through to
188 // ValidateSingleText() or ValidateQuotedQuotedTextEmbedded().
190 // Args: vrwArgContext - (RW) The command's argument options string.
191 // Return: MIstatus::success - Functional succeeded.
192 // MIstatus::failure - Functional failed.
196 CMICmdArgValString::ValidateQuotedText(CMICmdArgContext &vrwArgContext)
198 // CODETAG_QUOTEDTEXT_SIMILAR_CODE
199 CMIUtilString strOptions = vrwArgContext.GetArgsLeftToParse();
200 const MIchar cQuote = '"';
202 // Look for first quote of two
203 MIint nPos = strOptions.find(cQuote);
204 if (nPos == (MIint)std::string::npos)
205 return ValidateSingleText(vrwArgContext);
207 // Is one and only quote at end of the string
208 const MIint nLen = strOptions.length();
209 if (nPos == (MIint)(nLen - 1))
210 return MIstatus::failure;
212 // Quote must be the first character in the string or be preceeded by a space
213 if ((nPos > 0) && (strOptions[nPos - 1] != ' '))
214 return MIstatus::failure;
216 // Need to find the other quote
217 const MIint nPos2 = strOptions.rfind(cQuote);
218 if (nPos2 == (MIint)std::string::npos)
219 return MIstatus::failure;
221 // Is there quotes surrounding string formatting embedded quotes
222 if (IsStringArgQuotedQuotedTextEmbedded(strOptions))
223 return ValidateQuotedQuotedTextEmbedded(vrwArgContext);
225 // Make sure not same back quote, need two quotes
227 return MIstatus::failure;
229 // Extract quoted text
230 const CMIUtilString strQuotedTxt = strOptions.substr(nPos, nPos2 - nPos + 1).c_str();
231 if (vrwArgContext.RemoveArg(strQuotedTxt))
235 m_argValue = strOptions.substr(nPos + 1, nPos2 - nPos - 1).c_str();
236 return MIstatus::success;
239 return MIstatus::failure;
242 //++ ------------------------------------------------------------------------------------
243 // Details: Parse the command's argument options string and try to extract all the words
244 // between quotes then delimited by the next space. If there any string format
245 // characters '\\' used to embed quotes these are ignored i.e. "\\\"%5d\\\""
246 // becomes "%5d". Can fall through to ValidateQuotedText().
248 // Args: vrwArgContext - (RW) The command's argument options string.
249 // Return: MIstatus::success - Functional succeeded.
250 // MIstatus::failure - Functional failed.
254 CMICmdArgValString::ValidateQuotedTextEmbedded(CMICmdArgContext &vrwArgContext)
256 // CODETAG_QUOTEDTEXT_SIMILAR_CODE
257 CMIUtilString strOptions = vrwArgContext.GetArgsLeftToParse();
258 const MIchar cBckSlash = '\\';
259 const MIint nPos = strOptions.find(cBckSlash);
260 if (nPos == (MIint)std::string::npos)
261 return ValidateQuotedText(vrwArgContext);
263 // Back slash must be the first character in the string or be preceeded by a space
265 const MIchar cSpace = ' ';
266 if ((nPos > 0) && (strOptions[nPos - 1] != cSpace))
267 return MIstatus::failure;
269 // Need to find the other back slash
270 const MIint nPos2 = strOptions.rfind(cBckSlash);
271 if (nPos2 == (MIint)std::string::npos)
272 return MIstatus::failure;
274 // Make sure not same back slash, need two slashs
276 return MIstatus::failure;
278 // Look for the two quotes
279 const MIint nLen = strOptions.length();
280 const MIchar cQuote = '"';
281 const MIint nPosQuote1 = nPos + 1;
282 const MIint nPosQuote2 = (nPos2 < nLen) ? nPos2 + 1 : nPos2;
283 if ((nPosQuote1 != nPosQuote2) && (strOptions[nPosQuote1] != cQuote) && (strOptions[nPosQuote2] != cQuote))
284 return MIstatus::failure;
286 // Extract quoted text
287 const CMIUtilString strQuotedTxt = strOptions.substr(nPos, nPosQuote2 - nPos + 1).c_str();
288 if (vrwArgContext.RemoveArg(strQuotedTxt))
292 m_argValue = strQuotedTxt;
293 return MIstatus::success;
296 return MIstatus::failure;
299 //++ ------------------------------------------------------------------------------------
300 // Details: Parse the command's argument options string and try to extract all the words
301 // between quotes then delimited by the next space. If there any string format
302 // characters '\\' used to embed quotes these are ignored i.e. "\\\"%5d\\\""
305 // Args: vrwArgContext - (RW) The command's argument options string.
306 // Return: MIstatus::success - Functional succeeded.
307 // MIstatus::failure - Functional failed.
311 CMICmdArgValString::ValidateQuotedQuotedTextEmbedded(CMICmdArgContext &vrwArgContext)
313 // CODETAG_QUOTEDTEXT_SIMILAR_CODE
314 CMIUtilString strOptions = vrwArgContext.GetArgsLeftToParse();
315 const MIint nPos = strOptions.find("\"\\\"");
316 if (nPos == (MIint)std::string::npos)
317 return MIstatus::failure;
319 const MIint nPos2 = strOptions.rfind("\\\"\"");
320 if (nPos2 == (MIint)std::string::npos)
321 return MIstatus::failure;
323 const MIint nLen = strOptions.length();
324 if ((nLen > 5) && ((nPos + 2) == (nPos2 - 2)))
325 return MIstatus::failure;
327 // Quote must be the first character in the string or be preceeded by a space
329 const MIchar cSpace = ' ';
330 if ((nPos > 0) && (strOptions[nPos - 1] != cSpace))
331 return MIstatus::failure;
333 // Extract quoted text
334 const CMIUtilString strQuotedTxt = strOptions.substr(nPos, nPos2 - nPos + 3).c_str();
335 if (vrwArgContext.RemoveArg(strQuotedTxt))
339 m_argValue = strQuotedTxt;
340 return MIstatus::success;
343 return MIstatus::failure;
346 //++ ------------------------------------------------------------------------------------
347 // Details: Examine the string and determine if it is a valid string type argument.
349 // Args: vrTxt - (R) Some text.
350 // Return: bool - True = yes valid arg, false = no.
354 CMICmdArgValString::IsStringArg(const CMIUtilString &vrTxt) const
356 if (m_bHandleQuotedString)
357 return (IsStringArgQuotedText(vrTxt) || IsStringArgQuotedTextEmbedded(vrTxt) || IsStringArgQuotedQuotedTextEmbedded(vrTxt) ||
358 IsStringArgSingleText(vrTxt)); // Still test for this as could just be one word still
360 return IsStringArgSingleText(vrTxt);
363 //++ ------------------------------------------------------------------------------------
364 // Details: Examine the string and determine if it is a valid string type argument or
365 // option value. If the string looks like a long option, short option, a thread
366 // group ID or just a number it is rejected as a string type value. There is an
367 // option to allow the string to accept a number as a string type.
369 // Args: vrTxt - (R) Some text.
370 // Return: bool - True = yes valid argument value, false = something else.
374 CMICmdArgValString::IsStringArgSingleText(const CMIUtilString &vrTxt) const
376 // Accept anything as string word
377 if (m_bHandleAnything)
380 if (!m_bHandleDirPaths)
382 // Look for directory file paths, if found reject
383 const bool bHavePosSlash = (vrTxt.find_first_of("/") != std::string::npos);
384 const bool bHaveBckSlash = (vrTxt.find_first_of("\\") != std::string::npos);
385 if (bHavePosSlash || bHaveBckSlash)
389 // Look for --someLongOption, if found reject
390 if (0 == vrTxt.find("--"))
393 // Look for -f type short options, if found reject
394 if ((0 == vrTxt.find("-")) && (vrTxt.length() == 2))
397 // Look for thread group i1 i2 i3...., if found reject
398 if ((vrTxt.find("i") == 0) && ::isdigit(vrTxt[1]))
401 // Look for numbers, if found reject
402 if (!m_bAcceptNumbers && vrTxt.IsNumber())
408 //++ ------------------------------------------------------------------------------------
409 // Details: Examine the string and determine if it is a valid string type argument.
410 // Take into account quotes surrounding the text. Note this function falls
411 // through to IsStringArgSingleText() should the criteria match fail.
413 // Args: vrTxt - (R) Some text.
414 // Return: bool - True = yes valid arg, false = no.
418 CMICmdArgValString::IsStringArgQuotedText(const CMIUtilString &vrTxt) const
420 // CODETAG_QUOTEDTEXT_SIMILAR_CODE
421 const MIchar cQuote = '"';
422 const MIint nPos = vrTxt.find(cQuote);
423 if (nPos == (MIint)std::string::npos)
426 // Is one and only quote at end of the string
427 if (nPos == (MIint)(vrTxt.length() - 1))
430 // Quote must be the first character in the string or be preceeded by a space
431 // Also check for embedded string formating quote
432 const MIchar cBckSlash = '\\';
433 const MIchar cSpace = ' ';
434 if ((nPos > 1) && (vrTxt[nPos - 1] == cBckSlash) && (vrTxt[nPos - 2] != cSpace))
438 if ((nPos > 0) && (vrTxt[nPos - 1] != cSpace))
441 // Need to find the other quote
442 const MIint nPos2 = vrTxt.rfind(cQuote);
443 if (nPos2 == (MIint)std::string::npos)
446 // Make sure not same quote, need two quotes
448 return MIstatus::failure;
453 //++ ------------------------------------------------------------------------------------
454 // Details: Examine the string and determine if it is a valid string type argument.
455 // Take into account quotes surrounding the text. Take into account string format
456 // embedded quotes surrounding the text i.e. "\\\"%5d\\\"". Note this function falls
457 // through to IsStringArgQuotedText() should the criteria match fail.
459 // Args: vrTxt - (R) Some text.
460 // Return: bool - True = yes valid arg, false = no.
464 CMICmdArgValString::IsStringArgQuotedTextEmbedded(const CMIUtilString &vrTxt) const
466 // CODETAG_QUOTEDTEXT_SIMILAR_CODE
467 const MIchar cBckSlash = '\\';
468 const MIint nPos = vrTxt.find(cBckSlash);
469 if (nPos == (MIint)std::string::npos)
472 // Slash must be the first character in the string or be preceeded by a space
473 const MIchar cSpace = ' ';
474 if ((nPos > 0) && (vrTxt[nPos - 1] != cSpace))
477 // Need to find the other matching slash
478 const MIint nPos2 = vrTxt.rfind(cBckSlash);
479 if (nPos2 == (MIint)std::string::npos)
482 // Make sure not same back slash, need two slashs
484 return MIstatus::failure;
489 //++ ------------------------------------------------------------------------------------
490 // Details: Examine the string and determine if it is a valid string type argument.
491 // Take into account quotes surrounding the text. Take into account string format
492 // embedded quotes surrounding the text i.e. "\\\"%5d\\\"". Note this function falls
493 // through to IsStringArgQuotedTextEmbedded() should the criteria match fail.
495 // Args: vrTxt - (R) Some text.
496 // Return: bool - True = yes valid arg, false = no.
500 CMICmdArgValString::IsStringArgQuotedQuotedTextEmbedded(const CMIUtilString &vrTxt) const
502 const MIint nPos = vrTxt.find("\"\\\"");
503 if (nPos == (MIint)std::string::npos)
506 const MIint nPos2 = vrTxt.rfind("\\\"\"");
507 if (nPos2 == (MIint)std::string::npos)
510 const MIint nLen = vrTxt.length();
511 if ((nLen > 5) && ((nPos + 2) == (nPos2 - 2)))