Index: tools/lldb-mi/MIUtilString.h =================================================================== --- tools/lldb-mi/MIUtilString.h +++ tools/lldb-mi/MIUtilString.h @@ -66,6 +66,10 @@ CMIUtilString StripCRAll(void) const; CMIUtilString Trim(void) const; CMIUtilString Trim(const MIchar vChar) const; + MIuint FindFirst(const CMIUtilString &vrPattern, const MIuint vnPos = 0) const; + MIuint FindFirst(const CMIUtilString &vrPattern, const bool vbSkipQuotedText, bool &vrwbNotFoundClosedQuote, + const MIuint vnPos = 0) const; + MIuint FindFirstNot(const CMIUtilString &vrPattern, const MIuint vnPos = 0) const; // CMIUtilString &operator=(const MIchar *vpRhs); CMIUtilString &operator=(const std::string &vrRhs); @@ -82,4 +86,5 @@ private: bool ExtractNumberFromHexadecimal(MIint64 &vwrNumber) const; CMIUtilString RemoveRepeatedCharacters(const MIint vnPos, const MIchar vChar); + MIuint FindFirstQuote(const MIuint vnPos) const; }; Index: tools/lldb-mi/MIUtilString.cpp =================================================================== --- tools/lldb-mi/MIUtilString.cpp +++ tools/lldb-mi/MIUtilString.cpp @@ -224,40 +224,30 @@ if (this->empty() || vDelimiter.empty()) return 0; - MIint nPos = find(vDelimiter); - if (nPos == (MIint)std::string::npos) - { - vwVecSplits.push_back(*this); - return 1; - } - const MIint strLen(length()); - if (nPos == strLen) - { - vwVecSplits.push_back(*this); - return 1; - } + const MIuint nLen(length()); + MIuint nOffset(0); + do + { + // Find first occurrence which doesn't match to the delimiter + const MIuint nSectionPos(FindFirstNot(vDelimiter, nOffset)); + if (nSectionPos == (MIuint)std::string::npos) + break; - MIuint nAdd1(1); - if ((nPos > 0) && (substr(0, nPos) != vDelimiter)) - { - nPos = 0; - nAdd1 = 0; - } - MIint nPos2 = find(vDelimiter, nPos + 1); - while (nPos2 != (MIint)std::string::npos) - { - const MIuint len(nPos2 - nPos - nAdd1); - const std::string strSection(substr(nPos + nAdd1, len)); - if (strSection != vDelimiter) - vwVecSplits.push_back(strSection.c_str()); - nPos += len + 1; - nPos2 = find(vDelimiter, nPos + 1); - nAdd1 = 0; - } - const std::string strSection(substr(nPos, strLen - nPos)); - if ((strSection.length() != 0) && (strSection != vDelimiter)) + // Find next occurrence of the delimiter after section + MIuint nNextDelimiterPos(FindFirst(vDelimiter, nSectionPos)); + if (nNextDelimiterPos == (MIuint)std::string::npos) + nNextDelimiterPos = nLen; + + // Extract string between delimiters + const MIuint nSectionLen(nNextDelimiterPos - nSectionPos); + const std::string strSection(substr(nSectionPos, nSectionLen)); vwVecSplits.push_back(strSection.c_str()); + // Next + nOffset = nNextDelimiterPos + 1; + } + while (nOffset < nLen); + return vwVecSplits.size(); } @@ -283,81 +273,37 @@ if (this->empty() || vDelimiter.empty()) return 0; - MIint nPos = find(vDelimiter); - if (nPos == (MIint)std::string::npos) - { - vwVecSplits.push_back(*this); - return 1; - } - const MIint strLen(length()); - if (nPos == strLen) - { - vwVecSplits.push_back(*this); - return 1; - } + const MIuint nLen(length()); + MIuint nOffset(0); + do + { + // Find first occurrence which doesn't match to the delimiter + const MIuint nSectionPos(FindFirstNot(vDelimiter, nOffset)); + if (nSectionPos == (MIuint)std::string::npos) + break; - // Look for more quotes - bool bHaveQuotes = false; - const MIchar cBckSlash = '\\'; - const MIchar cQuote = '"'; - MIint nPosQ = find(cQuote); - MIint nPosQ2 = (MIint)std::string::npos; - if (nPosQ != (MIint)std::string::npos) - { - nPosQ2 = nPosQ + 1; - while (nPosQ2 < strLen) + // Find next occurrence of the delimiter after (quoted) section + const bool bSkipQuotedText(true); + bool bUnmatchedQuote(false); + MIuint nNextDelimiterPos(FindFirst(vDelimiter, bSkipQuotedText, bUnmatchedQuote, nSectionPos)); + if (bUnmatchedQuote) { - nPosQ2 = find(cQuote, nPosQ2); - if ((nPosQ2 == (MIint)std::string::npos) || (at(nPosQ2 - 1) != cBckSlash)) - break; - nPosQ2++; + vwVecSplits.clear(); + return 0; } - bHaveQuotes = (nPosQ2 != (MIint)std::string::npos); - } + if (nNextDelimiterPos == (MIuint)std::string::npos) + nNextDelimiterPos = nLen; - MIuint nAdd1(1); - if ((nPos > 0) && (substr(0, nPos) != vDelimiter)) - { - nPos = 0; - nAdd1 = 0; - } - MIint nPos2 = find(vDelimiter, nPos + 1); - while (nPos2 != (MIint)std::string::npos) - { - if (!bHaveQuotes || (bHaveQuotes && ((nPos2 > nPosQ2) || (nPos2 < nPosQ)))) - { - // Extract text or quoted text - const MIuint len(nPos2 - nPos - nAdd1); - const std::string strSection(substr(nPos + nAdd1, len)); - if (strSection != vDelimiter) - vwVecSplits.push_back(strSection.c_str()); - nPos += len + 1; - nPos2 = find(vDelimiter, nPos + 1); - nAdd1 = 0; - - if (bHaveQuotes && (nPos2 > nPosQ2)) - { - // Reset, look for more quotes - bHaveQuotes = false; - nPosQ = find(cQuote, nPos); - nPosQ2 = (MIint)std::string::npos; - if (nPosQ != (MIint)std::string::npos) - { - nPosQ2 = find(cQuote, nPosQ + 1); - bHaveQuotes = (nPosQ2 != (MIint)std::string::npos); - } - } - } - else - { - // Skip passed text in quotes - nPos2 = find(vDelimiter, nPosQ2 + 1); - } - } - const std::string strSection(substr(nPos, strLen - nPos)); - if ((strSection.length() != 0) && (strSection != vDelimiter)) + // Extract string between delimiters + const MIuint nSectionLen(nNextDelimiterPos - nSectionPos); + const std::string strSection(substr(nSectionPos, nSectionLen)); vwVecSplits.push_back(strSection.c_str()); + // Next + nOffset = nNextDelimiterPos + 1; + } + while (nOffset < nLen); + return vwVecSplits.size(); } @@ -696,3 +642,123 @@ return true; } + +//++ ------------------------------------------------------------------------------------ +// Details: Find first occurence in *this string which maches the pattern. +// Type: Method. +// Args: vrPattern - (R) The pattern to search for. +// vnPos - (R) The starting position at which to start searching. (Dflt = 0) +// Return: MIuint - The position of the first substring that match. +// Throws: None. +//-- +MIuint +CMIUtilString::FindFirst(const CMIUtilString &vrPattern, const MIuint vnPos /* = 0 */) const +{ + return find(vrPattern, vnPos); +} + +//++ ------------------------------------------------------------------------------------ +// Details: Find first occurence in *this string which maches the pattern and isn't surrounded by quotes. +// Type: Method. +// Args: vrPattern - (R) The pattern to search for. +// vbSkipQuotedText - (R) True = don't look at quoted text, false = otherwise. +// vrwbNotFoundClosedQuote - (W) True = parsing error: unmatched quote, false = otherwise. +// vnPos - (R) Position of the first character in the string to be considered in the search. (Dflt = 0) +// Return: MIuint - The position of the first substring that matches and isn't quoted. +// Throws: None. +//-- +MIuint +CMIUtilString::FindFirst(const CMIUtilString &vrPattern, const bool vbSkipQuotedText, bool &vrwbNotFoundClosedQuote, + const MIuint vnPos /* = 0 */) const +{ + vrwbNotFoundClosedQuote = false; + + if (!vbSkipQuotedText) + return FindFirst(vrPattern, vnPos); + + const MIuint nLen(length()); + + MIuint nPos = vnPos; + do + { + const MIuint nQuotePos(FindFirstQuote(nPos)); + const MIuint nPatternPos(FindFirst(vrPattern, nPos)); + if (nQuotePos == (MIuint)std::string::npos) + return nPatternPos; + + const MIuint nQuoteClosedPos = FindFirstQuote(nQuotePos + 1); + if (nQuoteClosedPos == (MIuint)std::string::npos) + { + vrwbNotFoundClosedQuote = true; + return (MIuint)std::string::npos; + } + + if ((nPatternPos == (MIuint)std::string::npos) || (nPatternPos < nQuotePos)) + return nPatternPos; + + nPos = nQuoteClosedPos + 1; + } + while (nPos < nLen); + + return (MIuint)std::string::npos; +} + +//++ ------------------------------------------------------------------------------------ +// Details: Find first occurence in *this string which doesn't mach to the pattern. +// Type: Method. +// Args: vrPattern - (R) The pattern to search for. +// vnPos - (R) Position of the first character in the string to be considered in the search. (Dflt = 0) +// Return: MIuint - The position of the first character that doesn't match. +// Throws: None. +//-- +MIuint +CMIUtilString::FindFirstNot(const CMIUtilString &vrPattern, const MIuint vnPos /* = 0 */) const +{ + const MIuint nLen(length()); + const MIuint nPatternLen(vrPattern.length()); + + MIuint nPatternPos(vnPos); + do + { + const bool bMatchPattern(compare(nPatternPos, nPatternLen, vrPattern) == 0); + if (!bMatchPattern) + return nPatternPos; + nPatternPos += nPatternLen; + } + while (nPatternPos < nLen); + + return (MIuint)std::string::npos; +} + +//++ ------------------------------------------------------------------------------------ +// Details: Find first occurence of not escaped quotation mark in *this string. +// Type: Method. +// Args: vnPos - (R) Position of the first character in the string to be considered in the search. +// Return: MIuint - The position of the quotation mark. +// Throws: None. +//-- +MIuint +CMIUtilString::FindFirstQuote(const MIuint vnPos) const +{ + const MIchar cBckSlash('\\'); + const MIchar cQuote('"'); + const MIuint nLen(length()); + + MIuint nPos = vnPos; + do + { + const MIuint nBckSlashPos(find(cBckSlash, nPos)); + const MIuint nQuotePos(find(cQuote, nPos)); + if ((nBckSlashPos == (MIuint)std::string::npos) || (nQuotePos == (MIuint)std::string::npos)) + return nQuotePos; + + if (nQuotePos < nBckSlashPos) + return nQuotePos; + + // Skip 2 characters: First is '\', second is that which is escaped by '\' + nPos = nBckSlashPos + 2; + } + while (nPos < nLen); + + return (MIuint)std::string::npos; +}