Index: tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp =================================================================== --- tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp +++ tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp @@ -1448,37 +1448,7 @@ bool CMICmnLLDBDebuggerHandleEvents::ConvertPrintfCtrlCodeToString(const MIchar vCtrl, CMIUtilString &vwrStrEquivalent) { - switch (vCtrl) - { - case '\033': - vwrStrEquivalent = "\\e"; - break; - case '\a': - vwrStrEquivalent = "\\a"; - break; - case '\b': - vwrStrEquivalent = "\\b"; - break; - case '\f': - vwrStrEquivalent = "\\f"; - break; - case '\n': - vwrStrEquivalent = "\\n"; - break; - case '\r': - vwrStrEquivalent = "\\r"; - break; - case '\t': - vwrStrEquivalent = "\\t"; - break; - case '\v': - vwrStrEquivalent = "\\v"; - break; - default: - vwrStrEquivalent = CMIUtilString::Format("%c", vCtrl); - break; - } - + vwrStrEquivalent = CMIUtilString::Format("%c", vCtrl).Escape(); return MIstatus::success; } Index: tools/lldb-mi/MIUtilString.h =================================================================== --- tools/lldb-mi/MIUtilString.h +++ tools/lldb-mi/MIUtilString.h @@ -72,6 +72,8 @@ 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 Escape(void) const; + CMIUtilString Unescape(void) const; // CMIUtilString &operator=(const MIchar *vpRhs); CMIUtilString &operator=(const std::string &vrRhs); @@ -89,4 +91,8 @@ bool ExtractNumberFromHexadecimal(MIint64 &vwrNumber) const; CMIUtilString RemoveRepeatedCharacters(const MIint vnPos, const MIchar vChar); MIuint FindFirstQuote(const MIuint vnPos) const; + + // Attributes: + private: + static const CMIUtilString ms_strEscapeCharacters; }; Index: tools/lldb-mi/MIUtilString.cpp =================================================================== --- tools/lldb-mi/MIUtilString.cpp +++ tools/lldb-mi/MIUtilString.cpp @@ -394,7 +394,7 @@ bool CMIUtilString::IsNumber(void) const { - if (empty()) + if (this->empty()) return false; if ((at(0) == '-') && (length() == 1)) @@ -797,3 +797,148 @@ return (MIuint)std::string::npos; } + +//++ ------------------------------------------------------------------------------------ +// Details: List of characters that should be escaped. +// Type: Member. +//-- +const CMIUtilString CMIUtilString::ms_strEscapeCharacters("\a\b\t\n\v\f\r\033\"'\\`"); + +//++ ------------------------------------------------------------------------------------ +// 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(void) const +{ + const MIchar cBckSlash('\\'); + const MIuint nLen(length()); + std::string strNew; + strNew.reserve(nLen); + MIuint nOffset(0); + while (nOffset < nLen) + { + const MIuint nEscapeCharPos(find_first_of(ms_strEscapeCharacters, nOffset)); + const bool bEscapeCharNotFound(nEscapeCharPos == (MIuint)std::string::npos); + if (bEscapeCharNotFound) + { + const MIuint nAppendAll((MIuint)std::string::npos); + strNew.append(*this, nOffset, nAppendAll); + break; + } + const MIuint nAppendLen(nEscapeCharPos - nOffset); + strNew.append(*this, nOffset, nAppendLen); + strNew.push_back(cBckSlash); + const MIchar cUnescapedChar(at(nEscapeCharPos)); + switch (cUnescapedChar) + { + case '\a': + strNew.push_back('a'); + break; + case '\b': + strNew.push_back('b'); + break; + case '\t': + strNew.push_back('t'); + break; + case '\n': + strNew.push_back('n'); + break; + case '\v': + strNew.push_back('v'); + break; + case '\f': + strNew.push_back('f'); + break; + case '\r': + strNew.push_back('r'); + break; + case '\033': + strNew.push_back('e'); + break; + default: + strNew.push_back(cUnescapedChar); + break; + } + nOffset = nEscapeCharPos + 1; + } + return CMIUtilString(strNew.c_str());; +} + +//++ ------------------------------------------------------------------------------------ +// Details: Get unescaped string from *this string. +// Type: Method. +// Args: None. +// Return: CMIUtilString - The unescaped version of the initial string. +// Throws: None. +//-- +CMIUtilString +CMIUtilString::Unescape(void) const +{ + const MIchar cBckSlash('\\'); + const MIuint nLen(length()); + std::string strNew; + strNew.reserve(nLen); + MIuint nOffset(0); + while (nOffset < nLen) + { + const MIuint nBckSlashPos(find(cBckSlash, nOffset)); + const bool bBckSlashNotFound(nBckSlashPos == (MIuint)std::string::npos); + if (bBckSlashNotFound) + { + const MIuint nAppendAll((MIuint)std::string::npos); + strNew.append(*this, nOffset, nAppendAll); + break; + } + const MIuint nAppendLen(nBckSlashPos - nOffset); + strNew.append(*this, nOffset, nAppendLen); + const bool bBckSlashIsLast(nBckSlashPos == nLen); + if (bBckSlashIsLast) + { + strNew.push_back(cBckSlash); + break; + } + const MIchar cEscapedChar(at(nBckSlashPos + 1)); + switch (cEscapedChar) + { + case 'a': + strNew.push_back('\a'); + break; + case 'b': + strNew.push_back('\b'); + break; + case 't': + strNew.push_back('\t'); + break; + case 'n': + strNew.push_back('\n'); + break; + case 'v': + strNew.push_back('\v'); + break; + case 'f': + strNew.push_back('\f'); + break; + case 'r': + strNew.push_back('\r'); + break; + case 'e': + strNew.push_back('\033'); + break; + default: + { + const MIuint nEscapedCharPos(ms_strEscapeCharacters.find(cEscapedChar)); + const bool bEscapedCharNotLegal(nEscapedCharPos == (MIuint)std::string::npos); + if (bEscapedCharNotLegal) + strNew.push_back(cBckSlash); + strNew.push_back(cEscapedChar); + break; + } + } + nOffset = nBckSlashPos + 2; + } + return CMIUtilString(strNew.c_str());; +}