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)
+ const MIuint nLen(length());
+ MIuint nOffset(0);
+ do
{
- 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();
}
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();
}
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;
+}