//===-- MICmdArgValString.cpp -----------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // In-house headers: #include "MICmdArgValString.h" #include "MICmdArgContext.h" //++ ------------------------------------------------------------------------------------ // Details: CMICmdArgValString constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmdArgValString::CMICmdArgValString() : m_bHandleQuotedString(false) , m_bAcceptNumbers(false) , m_bHandleDirPaths(false) , m_bHandleAnything(false) { } //++ ------------------------------------------------------------------------------------ // Details: CMICmdArgValString constructor. // Type: Method. // Args: vbAnything - (R) True = Parse a string and accept anything, false = do not accept anything. // Return: None. // Throws: None. //-- CMICmdArgValString::CMICmdArgValString(const bool vbAnything) : m_bHandleQuotedString(vbAnything ? true : false) , m_bAcceptNumbers(false) , m_bHandleDirPaths(false) , m_bHandleAnything(vbAnything) { } //++ ------------------------------------------------------------------------------------ // Details: CMICmdArgValString constructor. // Type: Method. // Args: vbHandleQuotes - (R) True = Parse a string surrounded by quotes spaces are not delimiters, false = only text up to // next delimiting space character. // vbAcceptNumbers - (R) True = Parse a string and accept as a number if number, false = numbers not recognised // as string types. // vbHandleDirPaths - (R) True = Parse a string and accept as a file path if a path, false = file paths are not // recognised as string types. // Return: None. // Throws: None. //-- CMICmdArgValString::CMICmdArgValString(const bool vbHandleQuotes, const bool vbAcceptNumbers, const bool vbHandleDirPaths) : m_bHandleQuotedString(vbHandleQuotes) , m_bAcceptNumbers(vbAcceptNumbers) , m_bHandleDirPaths(vbHandleDirPaths) , m_bHandleAnything(false) { } //++ ------------------------------------------------------------------------------------ // Details: CMICmdArgValString constructor. // Type: Method. // Args: vrArgName - (R) Argument's name to search by. // vbMandatory - (R) True = Yes must be present, false = optional argument. // vbHandleByCmd - (R) True = Command processes *this option, false = not handled. // vbHandleQuotes - (R) True = Parse a string surrounded by quotes spaces are not delimiters, false = only text up to // next delimiting space character. (Dflt = false) // vbAcceptNumbers - (R) True = Parse a string and accept as a number if number, false = numbers not recognised as // string types. (Dflt = false) // Return: None. // Throws: None. //-- CMICmdArgValString::CMICmdArgValString(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd, const bool vbHandleQuotes /* = false */, const bool vbAcceptNumbers /* = false */) : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd) , m_bHandleQuotedString(vbHandleQuotes) , m_bAcceptNumbers(vbAcceptNumbers) , m_bHandleDirPaths(false) , m_bHandleAnything(false) { } //++ ------------------------------------------------------------------------------------ // Details: CMICmdArgValString destructor. // Type: Overridden. // Args: None. // Return: None. // Throws: None. //-- CMICmdArgValString::~CMICmdArgValString() { } //++ ------------------------------------------------------------------------------------ // Details: Parse the command's argument options string and try to extract the value *this // argument is looking for. // Type: Overridden. // Args: vrwArgContext - (RW) The command's argument options string. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdArgValString::Validate(CMICmdArgContext &vrwArgContext) { if (vrwArgContext.IsEmpty()) return m_bMandatory ? MIstatus::failure : MIstatus::success; if (m_bHandleQuotedString) return ValidateQuotedText(vrwArgContext); return ValidateSingleText(vrwArgContext); } //++ ------------------------------------------------------------------------------------ // Details: Parse the command's argument options string and try to extract only the next // word delimited by the next space. // Type: Method. // Args: vrwArgContext - (RW) The command's argument options string. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdArgValString::ValidateSingleText(CMICmdArgContext &vrwArgContext) { const CMIUtilString::VecString_t vecOptions(vrwArgContext.GetArgs()); CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); while (it != vecOptions.end()) { const CMIUtilString &rArg(*it); if (IsStringArg(rArg)) { m_bFound = true; if (vrwArgContext.RemoveArg(rArg)) { m_bValid = true; m_argValue = rArg.StripSlashes(); return MIstatus::success; } else return MIstatus::failure; } // Next ++it; } return MIstatus::failure; } //++ ------------------------------------------------------------------------------------ // Details: Parse the command's argument options string and try to extract all the words // between quotes then delimited by the next space. // Type: Method. // Args: vrwArgContext - (RW) The command's argument options string. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdArgValString::ValidateQuotedText(CMICmdArgContext &vrwArgContext) { const CMIUtilString::VecString_t vecOptions(vrwArgContext.GetArgs()); if (vecOptions.size() == 0) return MIstatus::failure; const CMIUtilString &rArg(vecOptions[0]); if (!IsStringArg(rArg)) return MIstatus::failure; m_bFound = true; if (vrwArgContext.RemoveArg(rArg)) { m_bValid = true; const char cQuote = '"'; m_argValue = rArg.Trim(cQuote).StripSlashes(); return MIstatus::success; } return MIstatus::failure; } //++ ------------------------------------------------------------------------------------ // Details: Examine the string and determine if it is a valid string type argument. // Type: Method. // Args: vrTxt - (R) Some text. // Return: bool - True = yes valid arg, false = no. // Throws: None. //-- bool CMICmdArgValString::IsStringArg(const CMIUtilString &vrTxt) const { if (m_bHandleQuotedString) return (IsStringArgQuotedText(vrTxt) || IsStringArgQuotedTextEmbedded(vrTxt) || IsStringArgQuotedQuotedTextEmbedded(vrTxt) || IsStringArgSingleText(vrTxt)); // Still test for this as could just be one word still return IsStringArgSingleText(vrTxt); } //++ ------------------------------------------------------------------------------------ // Details: Examine the string and determine if it is a valid string type argument or // option value. If the string looks like a long option, short option, a thread // group ID or just a number it is rejected as a string type value. There is an // option to allow the string to accept a number as a string type. // Type: Method. // Args: vrTxt - (R) Some text. // Return: bool - True = yes valid argument value, false = something else. // Throws: None. //-- bool CMICmdArgValString::IsStringArgSingleText(const CMIUtilString &vrTxt) const { if (!m_bHandleDirPaths) { // Look for directory file paths, if found reject const bool bHavePosSlash = (vrTxt.find('/') != std::string::npos); const bool bHaveBckSlash = (vrTxt.find('\\') != std::string::npos); if (bHavePosSlash || bHaveBckSlash) return false; } // Look for --someLongOption, if found reject if (0 == vrTxt.find("--")) return false; // Look for -f type short options, if found reject if ((0 == vrTxt.find('-')) && (vrTxt.length() == 2)) return false; // Look for thread group i1 i2 i3...., if found reject if ((vrTxt.find('i') == 0) && ::isdigit(vrTxt[1])) return false; // Look for numbers, if found reject if (!m_bAcceptNumbers && vrTxt.IsNumber()) return false; return true; } //++ ------------------------------------------------------------------------------------ // Details: Examine the string and determine if it is a valid string type argument. // Take into account quotes surrounding the text. Note this function falls // through to IsStringArgSingleText() should the criteria match fail. // Type: Method. // Args: vrTxt - (R) Some text. // Return: bool - True = yes valid arg, false = no. // Throws: None. //-- bool CMICmdArgValString::IsStringArgQuotedText(const CMIUtilString &vrTxt) const { // Accept anything as string word if (m_bHandleAnything) return true; // CODETAG_QUOTEDTEXT_SIMILAR_CODE const char cQuote = '"'; const size_t nPos = vrTxt.find(cQuote); if (nPos == std::string::npos) return false; // Is one and only quote at end of the string if (nPos == (vrTxt.length() - 1)) return false; // Quote must be the first character in the string or be preceded by a space // Also check for embedded string formating quote const char cBckSlash = '\\'; const char cSpace = ' '; if ((nPos > 1) && (vrTxt[nPos - 1] == cBckSlash) && (vrTxt[nPos - 2] != cSpace)) { return false; } if ((nPos > 0) && (vrTxt[nPos - 1] != cSpace)) return false; // Need to find the other quote const size_t nPos2 = vrTxt.rfind(cQuote); if (nPos2 == std::string::npos) return false; // Make sure not same quote, need two quotes if (nPos == nPos2) return MIstatus::failure; return true; } //++ ------------------------------------------------------------------------------------ // Details: Examine the string and determine if it is a valid string type argument. // Take into account quotes surrounding the text. Take into account string format // embedded quotes surrounding the text i.e. "\\\"%5d\\\"". Note this function falls // through to IsStringArgQuotedText() should the criteria match fail. // Type: Method. // Args: vrTxt - (R) Some text. // Return: bool - True = yes valid arg, false = no. // Throws: None. //-- bool CMICmdArgValString::IsStringArgQuotedTextEmbedded(const CMIUtilString &vrTxt) const { // CODETAG_QUOTEDTEXT_SIMILAR_CODE const char cBckSlash = '\\'; const size_t nPos = vrTxt.find(cBckSlash); if (nPos == std::string::npos) return false; // Slash must be the first character in the string or be preceded by a space const char cSpace = ' '; if ((nPos > 0) && (vrTxt[nPos - 1] != cSpace)) return false; // Need to find the other matching slash const size_t nPos2 = vrTxt.rfind(cBckSlash); if (nPos2 == std::string::npos) return false; // Make sure not same back slash, need two slashes if (nPos == nPos2) return MIstatus::failure; return false; } //++ ------------------------------------------------------------------------------------ // Details: Examine the string and determine if it is a valid string type argument. // Take into account quotes surrounding the text. Take into account string format // embedded quotes surrounding the text i.e. "\\\"%5d\\\"". Note this function falls // through to IsStringArgQuotedTextEmbedded() should the criteria match fail. // Type: Method. // Args: vrTxt - (R) Some text. // Return: bool - True = yes valid arg, false = no. // Throws: None. //-- bool CMICmdArgValString::IsStringArgQuotedQuotedTextEmbedded(const CMIUtilString &vrTxt) const { const size_t nPos = vrTxt.find("\"\\\""); if (nPos == std::string::npos) return false; const size_t nPos2 = vrTxt.rfind("\\\"\""); if (nPos2 == std::string::npos) return false; const size_t nLen = vrTxt.length(); if ((nLen > 5) && ((nPos + 2) == (nPos2 - 2))) return false; return true; }