Fix CMIUtilString::SplitConsiderQuotes (MI)

Summary:
This method doesn't work properly. Here is an example:
```
CMIUtilString test("\"hello\" \"\\\" world \\\" !\"");
CMIUtilString::VecString_t res;
test.SplitConsiderQuotes(" ", res);
```

Before this patch the result was as following:
```
(lldb) print res
(CMIUtilString::VecString_t) $1 = size=4 {
  [0] = (std::__1::string = "\"hello\"")
  [1] = (std::__1::string = "\"\\\"")
  [2] = (std::__1::string = "world")
  [3] = (std::__1::string = "\\\" !\"")
}
```

This patch fixes that error and now it looks like following:
```
(lldb) print res
(CMIUtilString::VecString_t) $1 = size=2 {
  [0] = (std::__1::string = "\"hello\"")
  [1] = (std::__1::string = "\"\\\" world \\\" !\"")
}
```

Reviewers: abidh, emaste, clayborg

Reviewed By: clayborg

Subscribers: lldb-commits, emaste, clayborg, abidh

Differential Revision: http://reviews.llvm.org/D7532

llvm-svn: 228802
This commit is contained in:
Ilia K 2015-02-11 04:52:54 +00:00
parent 81b5c668ac
commit 98bdc6418f
2 changed files with 169 additions and 98 deletions

View File

@ -224,40 +224,30 @@ CMIUtilString::Split(const CMIUtilString &vDelimiter, VecString_t &vwVecSplits)
if (this->empty() || vDelimiter.empty())
return 0;
MIint nPos = find(vDelimiter);
if (nPos == (MIint)std::string::npos)
const MIuint nLen(length());
MIuint nOffset(0);
do
{
vwVecSplits.push_back(*this);
return 1;
}
const MIint strLen(length());
if (nPos == strLen)
{
vwVecSplits.push_back(*this);
return 1;
}
// 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 @@ CMIUtilString::SplitConsiderQuotes(const CMIUtilString &vDelimiter, VecString_t
if (this->empty() || vDelimiter.empty())
return 0;
MIint nPos = find(vDelimiter);
if (nPos == (MIint)std::string::npos)
const MIuint nLen(length());
MIuint nOffset(0);
do
{
vwVecSplits.push_back(*this);
return 1;
}
const MIint strLen(length());
if (nPos == strLen)
{
vwVecSplits.push_back(*this);
return 1;
}
// 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 @@ CMIUtilString::IsQuoted(void) const
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;
}

View File

@ -66,6 +66,10 @@ class CMIUtilString : public std::string
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 @@ class CMIUtilString : public std::string
private:
bool ExtractNumberFromHexadecimal(MIint64 &vwrNumber) const;
CMIUtilString RemoveRepeatedCharacters(const MIint vnPos, const MIchar vChar);
MIuint FindFirstQuote(const MIuint vnPos) const;
};