summaryrefslogtreecommitdiff
path: root/tools/lldb-mi/MIUtilString.cpp
diff options
context:
space:
mode:
authorEd Maste <emaste@FreeBSD.org>2015-07-03 16:57:06 +0000
committerEd Maste <emaste@FreeBSD.org>2015-07-03 16:57:06 +0000
commit5e95aa85bb660d45e9905ef1d7180b2678280660 (patch)
tree3c2e41c3be19b7fc7666ed45a5f91ec3b6e35f2a /tools/lldb-mi/MIUtilString.cpp
parent12bd4897ff0678fa663e09d78ebc22dd255ceb86 (diff)
Notes
Diffstat (limited to 'tools/lldb-mi/MIUtilString.cpp')
-rw-r--r--tools/lldb-mi/MIUtilString.cpp583
1 files changed, 417 insertions, 166 deletions
diff --git a/tools/lldb-mi/MIUtilString.cpp b/tools/lldb-mi/MIUtilString.cpp
index 0464eadccbff1..fc7717749da89 100644
--- a/tools/lldb-mi/MIUtilString.cpp
+++ b/tools/lldb-mi/MIUtilString.cpp
@@ -7,24 +7,13 @@
//
//===----------------------------------------------------------------------===//
-//++
-// File: MIUtilString.h
-//
-// Overview: CMIUtilString implementation.
-//
-// Environment: Compilers: Visual C++ 12.
-// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
-// Libraries: See MIReadmetxt.
-//
-// Copyright: None.
-//--
-
// Third party headers
-#include <memory> // std::unique_ptr
-#include <stdarg.h> // va_list, va_start, var_end
-#include <sstream> // std::stringstream
-#include <string.h> // for strcpy
-#include <limits.h> // for ULONG_MAX
+#include <inttypes.h> // for PRIx8
+#include <limits.h> // for ULONG_MAX
+#include <memory> // std::unique_ptr
+#include <sstream> // std::stringstream
+#include <stdarg.h> // va_list, va_start, var_end
+#include <string.h> // for strncmp
// In-house headers:
#include "MIUtilString.h"
@@ -48,7 +37,7 @@ CMIUtilString::CMIUtilString(void)
// Return: None.
// Throws: None.
//--
-CMIUtilString::CMIUtilString(const MIchar *vpData)
+CMIUtilString::CMIUtilString(const char *vpData)
: std::string(vpData)
{
}
@@ -60,19 +49,19 @@ CMIUtilString::CMIUtilString(const MIchar *vpData)
// Return: None.
// Throws: None.
//--
-CMIUtilString::CMIUtilString(const MIchar *const *vpData)
+CMIUtilString::CMIUtilString(const char *const *vpData)
: std::string((const char *)vpData)
{
}
//++ ------------------------------------------------------------------------------------
-// Details: CMIUtilString assigment operator.
+// Details: CMIUtilString assignment operator.
// Type: Method.
// Args: vpRhs - Pointer to UTF8 text data.
// Return: CMIUtilString & - *this string.
// Throws: None.
//--
-CMIUtilString &CMIUtilString::operator=(const MIchar *vpRhs)
+CMIUtilString &CMIUtilString::operator=(const char *vpRhs)
{
if (*this == vpRhs)
return *this;
@@ -86,7 +75,7 @@ CMIUtilString &CMIUtilString::operator=(const MIchar *vpRhs)
}
//++ ------------------------------------------------------------------------------------
-// Details: CMIUtilString assigment operator.
+// Details: CMIUtilString assignment operator.
// Type: Method.
// Args: vrRhs - The other string to copy from.
// Return: CMIUtilString & - *this string.
@@ -213,10 +202,10 @@ CMIUtilString::FormatValist(const CMIUtilString &vrFormating, va_list vArgs)
// Args: vData - (R) String data to be split up.
// vDelimiter - (R) Delimiter char or text.
// vwVecSplits - (W) Container of splits found in string data.
-// Return: MIuint - Number of splits found in the string data.
+// Return: size_t - Number of splits found in the string data.
// Throws: None.
//--
-MIuint
+size_t
CMIUtilString::Split(const CMIUtilString &vDelimiter, VecString_t &vwVecSplits) const
{
vwVecSplits.clear();
@@ -224,40 +213,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 size_t nLen(length());
+ size_t 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 size_t nSectionPos(FindFirstNot(vDelimiter, nOffset));
+ if (nSectionPos == 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
+ size_t nNextDelimiterPos(FindFirst(vDelimiter, nSectionPos));
+ if (nNextDelimiterPos == std::string::npos)
+ nNextDelimiterPos = nLen;
+
+ // Extract string between delimiters
+ const size_t 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();
}
@@ -265,17 +244,17 @@ CMIUtilString::Split(const CMIUtilString &vDelimiter, VecString_t &vwVecSplits)
// Details: Splits string into array of strings using delimiter. However the string is
// also considered for text surrounded by quotes. Text with quotes including the
// delimiter is treated as a whole. If multiple delimiter are found in sequence
-// then they are not added to the list of splits. Quotes that are embedded in the
+// then they are not added to the list of splits. Quotes that are embedded in
// the string as string formatted quotes are ignored (proceeded by a '\\') i.e.
// "\"MI GDB local C++.cpp\":88".
// Type: Method.
// Args: vData - (R) String data to be split up.
// vDelimiter - (R) Delimiter char or text.
// vwVecSplits - (W) Container of splits found in string data.
-// Return: MIuint - Number of splits found in the string data.
+// Return: size_t - Number of splits found in the string data.
// Throws: None.
//--
-MIuint
+size_t
CMIUtilString::SplitConsiderQuotes(const CMIUtilString &vDelimiter, VecString_t &vwVecSplits) const
{
vwVecSplits.clear();
@@ -283,85 +262,54 @@ 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 size_t nLen(length());
+ size_t 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 size_t nSectionPos(FindFirstNot(vDelimiter, nOffset));
+ if (nSectionPos == 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);
+ size_t 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 == 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 size_t 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();
}
//++ ------------------------------------------------------------------------------------
+// Details: Split string into lines using \n and return an array of strings.
+// Type: Method.
+// Args: vwVecSplits - (W) Container of splits found in string data.
+// Return: size_t - Number of splits found in the string data.
+// Throws: None.
+//--
+size_t
+CMIUtilString::SplitLines(VecString_t &vwVecSplits) const
+{
+ return Split("\n", vwVecSplits);
+}
+
+//++ ------------------------------------------------------------------------------------
// Details: Remove '\n' from the end of string if found. It does not alter
// *this string.
// Type: Method.
@@ -372,8 +320,8 @@ CMIUtilString::SplitConsiderQuotes(const CMIUtilString &vDelimiter, VecString_t
CMIUtilString
CMIUtilString::StripCREndOfLine(void) const
{
- const MIint nPos = rfind('\n');
- if (nPos == (MIint)std::string::npos)
+ const size_t nPos = rfind('\n');
+ if (nPos == std::string::npos)
return *this;
const CMIUtilString strNew(substr(0, nPos).c_str());
@@ -410,12 +358,12 @@ CMIUtilString::FindAndReplace(const CMIUtilString &vFind, const CMIUtilString &v
if (vFind.empty() || this->empty())
return *this;
- MIint nPos = find(vFind);
- if (nPos == (MIint)std::string::npos)
+ size_t nPos = find(vFind);
+ if (nPos == std::string::npos)
return *this;
CMIUtilString strNew(*this);
- while (nPos != (MIint)std::string::npos)
+ while (nPos != std::string::npos)
{
strNew.replace(nPos, vFind.length(), vReplaceWith);
nPos += vReplaceWith.length();
@@ -441,8 +389,30 @@ CMIUtilString::IsNumber(void) const
if ((at(0) == '-') && (length() == 1))
return false;
- const MIint nPos = find_first_not_of("-.0123456789");
- if (nPos != (MIint)std::string::npos)
+ const size_t nPos = find_first_not_of("-.0123456789");
+ if (nPos != std::string::npos)
+ return false;
+
+ return true;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Check if *this string is a hexadecimal number.
+// Type: Method.
+// Args: None.
+// Return: bool - True = yes number, false not a number.
+// Throws: None.
+//--
+bool
+CMIUtilString::IsHexadecimalNumber(void) const
+{
+ // Compare '0x..' prefix
+ if ((strncmp(c_str(), "0x", 2) != 0) && (strncmp(c_str(), "0X", 2) != 0))
+ return false;
+
+ // Skip '0x..' prefix
+ const size_t nPos = find_first_not_of("01234567890ABCDEFabcedf", 2);
+ if (nPos != std::string::npos)
return false;
return true;
@@ -452,7 +422,7 @@ CMIUtilString::IsNumber(void) const
// Details: Extract the number from the string. The number can be either a hexadecimal or
// natural number. It cannot contain other non-numeric characters.
// Type: Method.
-// Args: vwrNumber - (W) Number exracted from the string.
+// Args: vwrNumber - (W) Number extracted from the string.
// Return: bool - True = yes number, false not a number.
// Throws: None.
//--
@@ -478,7 +448,7 @@ CMIUtilString::ExtractNumber(MIint64 &vwrNumber) const
//++ ------------------------------------------------------------------------------------
// Details: Extract the number from the hexadecimal string..
// Type: Method.
-// Args: vwrNumber - (W) Number exracted from the string.
+// Args: vwrNumber - (W) Number extracted from the string.
// Return: bool - True = yes number, false not a number.
// Throws: None.
//--
@@ -487,16 +457,16 @@ CMIUtilString::ExtractNumberFromHexadecimal(MIint64 &vwrNumber) const
{
vwrNumber = 0;
- const MIint nPos = find_first_not_of("x01234567890ABCDEFabcedf");
- if (nPos != (MIint)std::string::npos)
+ const size_t nPos = find_first_not_of("xX01234567890ABCDEFabcedf");
+ if (nPos != std::string::npos)
return false;
- const MIint64 nNum = ::strtoul(this->c_str(), nullptr, 16);
- if (nNum != LONG_MAX)
- {
- vwrNumber = nNum;
- return true;
- }
+ errno = 0;
+ const MIuint64 nNum = ::strtoull(this->c_str(), nullptr, 16);
+ if (errno == ERANGE)
+ return false;
+
+ vwrNumber = static_cast<MIint64>(nNum);
return true;
}
@@ -505,21 +475,20 @@ CMIUtilString::ExtractNumberFromHexadecimal(MIint64 &vwrNumber) const
// Details: Determine if the text is all valid alpha numeric characters. Letters can be
// either upper or lower case.
// Type: Static method.
-// Args: vrText - (R) The text data to examine.
+// Args: vpText - (R) The text data to examine.
// Return: bool - True = yes all alpha, false = one or more chars is non alpha.
// Throws: None.
//--
bool
-CMIUtilString::IsAllValidAlphaAndNumeric(const MIchar &vrText)
+CMIUtilString::IsAllValidAlphaAndNumeric(const char *vpText)
{
- const MIuint len = ::strlen(&vrText);
+ const size_t len = ::strlen(vpText);
if (len == 0)
return false;
- MIchar *pPtr = const_cast<MIchar *>(&vrText);
- for (MIuint i = 0; i < len; i++, pPtr++)
+ for (size_t i = 0; i < len; i++, vpText++)
{
- const MIchar c = *pPtr;
+ const char c = *vpText;
if (::isalnum((int)c) == 0)
return false;
}
@@ -556,14 +525,14 @@ CMIUtilString
CMIUtilString::Trim(void) const
{
CMIUtilString strNew(*this);
- const MIchar *pWhiteSpace = " \t\n\v\f\r";
- const MIint nPos = find_last_not_of(pWhiteSpace);
- if (nPos != (MIint)std::string::npos)
+ const char *pWhiteSpace = " \t\n\v\f\r";
+ const size_t nPos = find_last_not_of(pWhiteSpace);
+ if (nPos != std::string::npos)
{
strNew = substr(0, nPos + 1).c_str();
}
- const MIint nPos2 = strNew.find_first_not_of(pWhiteSpace);
- if (nPos2 != (MIint)std::string::npos)
+ const size_t nPos2 = strNew.find_first_not_of(pWhiteSpace);
+ if (nPos2 != std::string::npos)
{
strNew = strNew.substr(nPos2).c_str();
}
@@ -579,10 +548,10 @@ CMIUtilString::Trim(void) const
// Throws: None.
//--
CMIUtilString
-CMIUtilString::Trim(const MIchar vChar) const
+CMIUtilString::Trim(const char vChar) const
{
CMIUtilString strNew(*this);
- const MIint nLen = strNew.length();
+ const size_t nLen = strNew.length();
if (nLen > 1)
{
if ((strNew[0] == vChar) && (strNew[nLen - 1] == vChar))
@@ -615,7 +584,7 @@ CMIUtilString::FormatBinary(const MIuint64 vnDecimal)
nNum = nNum >> 1;
nLen++;
}
- MIchar pN[nConstBits + 1];
+ char pN[nConstBits + 1];
MIuint j = 0;
for (i = nLen; i > 0; --i, j++)
{
@@ -637,7 +606,7 @@ CMIUtilString::FormatBinary(const MIuint64 vnDecimal)
// Throws: None.
//--
CMIUtilString
-CMIUtilString::RemoveRepeatedCharacters(const MIchar vChar)
+CMIUtilString::RemoveRepeatedCharacters(const char vChar)
{
return RemoveRepeatedCharacters(0, vChar);
}
@@ -648,22 +617,22 @@ CMIUtilString::RemoveRepeatedCharacters(const MIchar vChar)
// character.
// Type: Method.
// Args: vChar - (R) The character to search for and remove adjacent duplicates.
-// vnPos - (R) Character position in the string.
+// vnPos - Character position in the string.
// Return: CMIUtilString - New version of the string.
// Throws: None.
//--
CMIUtilString
-CMIUtilString::RemoveRepeatedCharacters(const MIint vnPos, const MIchar vChar)
+CMIUtilString::RemoveRepeatedCharacters(size_t vnPos, const char vChar)
{
- const MIchar cQuote = '"';
+ const char cQuote = '"';
// Look for first quote of two
- MIint nPos = find(cQuote, vnPos);
- if (nPos == (MIint)std::string::npos)
+ const size_t nPos = find(cQuote, vnPos);
+ if (nPos == std::string::npos)
return *this;
- const MIint nPosNext = nPos + 1;
- if (nPosNext > (MIint)length())
+ const size_t nPosNext = nPos + 1;
+ if (nPosNext > length())
return *this;
if (at(nPosNext) == cQuote)
@@ -685,14 +654,296 @@ CMIUtilString::RemoveRepeatedCharacters(const MIint vnPos, const MIchar vChar)
bool
CMIUtilString::IsQuoted(void) const
{
- const MIchar cQuote = '"';
+ const char cQuote = '"';
if (at(0) != cQuote)
return false;
- const MIint nLen = length();
+ const size_t nLen = length();
if ((nLen > 0) && (at(nLen - 1) != cQuote))
return false;
return true;
}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Find first occurrence in *this string which matches the pattern.
+// Type: Method.
+// Args: vrPattern - (R) The pattern to search for.
+// vnPos - The starting position at which to start searching. (Dflt = 0)
+// Return: size_t - The position of the first substring that match.
+// Throws: None.
+//--
+size_t
+CMIUtilString::FindFirst(const CMIUtilString &vrPattern, size_t vnPos /* = 0 */) const
+{
+ return find(vrPattern, vnPos);
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Find first occurrence in *this string which matches 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 - Position of the first character in the string to be considered in the search. (Dflt = 0)
+// Return: size_t - The position of the first substring that matches and isn't quoted.
+// Throws: None.
+//--
+size_t
+CMIUtilString::FindFirst(const CMIUtilString &vrPattern, const bool vbSkipQuotedText, bool &vrwbNotFoundClosedQuote,
+ size_t vnPos /* = 0 */) const
+{
+ vrwbNotFoundClosedQuote = false;
+
+ if (!vbSkipQuotedText)
+ return FindFirst(vrPattern, vnPos);
+
+ const size_t nLen(length());
+
+ size_t nPos = vnPos;
+ do
+ {
+ const size_t nQuotePos(FindFirstQuote(nPos));
+ const size_t nPatternPos(FindFirst(vrPattern, nPos));
+ if (nQuotePos == std::string::npos)
+ return nPatternPos;
+
+ const size_t nQuoteClosedPos = FindFirstQuote(nQuotePos + 1);
+ if (nQuoteClosedPos == std::string::npos)
+ {
+ vrwbNotFoundClosedQuote = true;
+ return std::string::npos;
+ }
+
+ if ((nPatternPos == std::string::npos) || (nPatternPos < nQuotePos))
+ return nPatternPos;
+
+ nPos = nQuoteClosedPos + 1;
+ }
+ while (nPos < nLen);
+
+ return std::string::npos;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Find first occurrence in *this string which doesn't match the pattern.
+// Type: Method.
+// Args: vrPattern - (R) The pattern to search for.
+// vnPos - Position of the first character in the string to be considered in the search. (Dflt = 0)
+// Return: size_t - The position of the first character that doesn't match.
+// Throws: None.
+//--
+size_t
+CMIUtilString::FindFirstNot(const CMIUtilString &vrPattern, size_t vnPos /* = 0 */) const
+{
+ const size_t nLen(length());
+ const size_t nPatternLen(vrPattern.length());
+
+ size_t nPatternPos(vnPos);
+ do
+ {
+ const bool bMatchPattern(compare(nPatternPos, nPatternLen, vrPattern) == 0);
+ if (!bMatchPattern)
+ return nPatternPos;
+ nPatternPos += nPatternLen;
+ }
+ while (nPatternPos < nLen);
+
+ return std::string::npos;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Find first occurrence of not escaped quotation mark in *this string.
+// Type: Method.
+// Args: vnPos - Position of the first character in the string to be considered in the search.
+// Return: size_t - The position of the quotation mark.
+// Throws: None.
+//--
+size_t
+CMIUtilString::FindFirstQuote(size_t vnPos) const
+{
+ const char cBckSlash('\\');
+ const char cQuote('"');
+ const size_t nLen(length());
+
+ size_t nPos = vnPos;
+ do
+ {
+ const size_t nBckSlashPos(find(cBckSlash, nPos));
+ const size_t nQuotePos(find(cQuote, nPos));
+ if ((nBckSlashPos == std::string::npos) || (nQuotePos == 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 std::string::npos;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Get escaped string from *this string.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - The escaped version of the initial string.
+// Throws: None.
+//--
+CMIUtilString
+CMIUtilString::Escape(bool vbEscapeQuotes /* = false */) const
+{
+ const size_t nLen(length());
+ CMIUtilString strNew;
+ strNew.reserve(nLen);
+ for (size_t nIndex(0); nIndex < nLen; ++nIndex)
+ {
+ const char cUnescapedChar((*this)[nIndex]);
+ if (cUnescapedChar == '"' && vbEscapeQuotes)
+ strNew.append("\\\"");
+ else
+ strNew.append(ConvertToPrintableASCII((char)cUnescapedChar));
+ }
+ return strNew;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Get string with backslashes in front of double quote '"' and backslash '\\'
+// characters.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - The wrapped version of the initial string.
+// Throws: None.
+//--
+CMIUtilString
+CMIUtilString::AddSlashes(void) const
+{
+ const char cBckSlash('\\');
+ const size_t nLen(length());
+ CMIUtilString strNew;
+ strNew.reserve(nLen);
+
+ size_t nOffset(0);
+ while (nOffset < nLen)
+ {
+ const size_t nUnescapedCharPos(find_first_of("\"\\", nOffset));
+ const bool bUnescapedCharNotFound(nUnescapedCharPos == std::string::npos);
+ if (bUnescapedCharNotFound)
+ {
+ const size_t nAppendAll(std::string::npos);
+ strNew.append(*this, nOffset, nAppendAll);
+ break;
+ }
+ const size_t nAppendLen(nUnescapedCharPos - nOffset);
+ strNew.append(*this, nOffset, nAppendLen);
+ strNew.push_back(cBckSlash);
+ const char cUnescapedChar((*this)[nUnescapedCharPos]);
+ strNew.push_back(cUnescapedChar);
+ nOffset = nUnescapedCharPos + 1;
+ }
+
+ return strNew;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Remove backslashes added by CMIUtilString::AddSlashes.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - The initial version of wrapped string.
+// Throws: None.
+//--
+CMIUtilString
+CMIUtilString::StripSlashes(void) const
+{
+ const char cBckSlash('\\');
+ const size_t nLen(length());
+ CMIUtilString strNew;
+ strNew.reserve(nLen);
+
+ size_t nOffset(0);
+ while (nOffset < nLen)
+ {
+ const size_t nBckSlashPos(find(cBckSlash, nOffset));
+ const bool bBckSlashNotFound(nBckSlashPos == std::string::npos);
+ if (bBckSlashNotFound)
+ {
+ const size_t nAppendAll(std::string::npos);
+ strNew.append(*this, nOffset, nAppendAll);
+ break;
+ }
+ const size_t nAppendLen(nBckSlashPos - nOffset);
+ strNew.append(*this, nOffset, nAppendLen);
+ const bool bBckSlashIsLast(nBckSlashPos == nLen);
+ if (bBckSlashIsLast)
+ {
+ strNew.push_back(cBckSlash);
+ break;
+ }
+ const char cEscapedChar((*this)[nBckSlashPos + 1]);
+ const size_t nEscapedCharPos(std::string("\"\\").find(cEscapedChar));
+ const bool bEscapedCharNotFound(nEscapedCharPos == std::string::npos);
+ if (bEscapedCharNotFound)
+ strNew.push_back(cBckSlash);
+ strNew.push_back(cEscapedChar);
+ nOffset = nBckSlashPos + 2;
+ }
+
+ return strNew;
+}
+
+CMIUtilString
+CMIUtilString::ConvertToPrintableASCII(const char vChar)
+{
+ switch (vChar)
+ {
+ case '\a':
+ return "\\a";
+ case '\b':
+ return "\\b";
+ case '\t':
+ return "\\t";
+ case '\n':
+ return "\\n";
+ case '\v':
+ return "\\v";
+ case '\f':
+ return "\\f";
+ case '\r':
+ return "\\r";
+ case '\033':
+ return "\\e";
+ case '\\':
+ return "\\\\";
+ default:
+ if (::isprint(vChar))
+ return Format("%c", vChar);
+ else
+ return Format("\\x%02" PRIx8, vChar);
+ }
+}
+
+CMIUtilString
+CMIUtilString::ConvertToPrintableASCII(const char16_t vChar16)
+{
+ if (vChar16 == (char16_t)(char)vChar16 && ::isprint(vChar16))
+ // Convert char16_t to char (if possible)
+ return Format("%c", vChar16);
+ else
+ return Format("\\u%02" PRIx8 "%02" PRIx8,
+ (vChar16 >> 8) & 0xff, vChar16 & 0xff);
+}
+
+CMIUtilString
+CMIUtilString::ConvertToPrintableASCII(const char32_t vChar32)
+{
+ if (vChar32 == (char32_t)(char)vChar32 && ::isprint(vChar32))
+ // Convert char32_t to char (if possible)
+ return Format("%c", vChar32);
+ else
+ return Format("\\U%02" PRIx8 "%02" PRIx8 "%02" PRIx8 "%02" PRIx8,
+ (vChar32 >> 24) & 0xff, (vChar32 >> 16) & 0xff,
+ (vChar32 >> 8) & 0xff, vChar32 & 0xff);
+}