forked from OSchip/llvm-project
962 lines
29 KiB
C++
962 lines
29 KiB
C++
//===-- MIUtilString.cpp ----------------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Third party headers
|
|
#include <cstdlib>
|
|
#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"
|
|
|
|
//++
|
|
//------------------------------------------------------------------------------------
|
|
// Details: CMIUtilString constructor.
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: None.
|
|
// Throws: None.
|
|
//--
|
|
CMIUtilString::CMIUtilString() : std::string() {}
|
|
|
|
//++
|
|
//------------------------------------------------------------------------------------
|
|
// Details: CMIUtilString constructor.
|
|
// Type: Method.
|
|
// Args: vpData - Pointer to UTF8 text data.
|
|
// Return: None.
|
|
// Throws: None.
|
|
//--
|
|
CMIUtilString::CMIUtilString(const char *vpData) : std::string(vpData) {}
|
|
|
|
//++
|
|
//------------------------------------------------------------------------------------
|
|
// Details: CMIUtilString constructor.
|
|
// Type: Method.
|
|
// Args: vpStr - Text data.
|
|
// Return: None.
|
|
// Throws: None.
|
|
//--
|
|
CMIUtilString::CMIUtilString(const std::string &vrStr) : std::string(vrStr) {}
|
|
|
|
//++
|
|
//------------------------------------------------------------------------------------
|
|
// Details: CMIUtilString assignment operator.
|
|
// Type: Method.
|
|
// Args: vpRhs - Pointer to UTF8 text data.
|
|
// Return: CMIUtilString & - *this string.
|
|
// Throws: None.
|
|
//--
|
|
CMIUtilString &CMIUtilString::operator=(const char *vpRhs) {
|
|
assign(vpRhs);
|
|
return *this;
|
|
}
|
|
|
|
//++
|
|
//------------------------------------------------------------------------------------
|
|
// Details: CMIUtilString assignment operator.
|
|
// Type: Method.
|
|
// Args: vrRhs - The other string to copy from.
|
|
// Return: CMIUtilString & - *this string.
|
|
// Throws: None.
|
|
//--
|
|
CMIUtilString &CMIUtilString::operator=(const std::string &vrRhs) {
|
|
assign(vrRhs);
|
|
return *this;
|
|
}
|
|
|
|
//++
|
|
//------------------------------------------------------------------------------------
|
|
// Details: CMIUtilString destructor.
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: None.
|
|
// Throws: None.
|
|
//--
|
|
CMIUtilString::~CMIUtilString() {}
|
|
|
|
//++
|
|
//------------------------------------------------------------------------------------
|
|
// Details: Perform a snprintf format style on a string data. A new string
|
|
// object is
|
|
// created and returned.
|
|
// Type: Static method.
|
|
// Args: vrFormat - (R) Format string data instruction.
|
|
// vArgs - (R) Var list args of any type.
|
|
// Return: CMIUtilString - Number of splits found in the string data.
|
|
// Throws: None.
|
|
//--
|
|
CMIUtilString CMIUtilString::FormatPriv(const CMIUtilString &vrFormat,
|
|
va_list vArgs) {
|
|
CMIUtilString strResult;
|
|
MIint nFinal = 0;
|
|
MIint n = vrFormat.size();
|
|
|
|
// IOR: mysterious crash in this function on some windows builds not able to
|
|
// duplicate
|
|
// but found article which may be related. Crash occurs in vsnprintf() or
|
|
// va_copy()
|
|
// Duplicate vArgs va_list argument pointer to ensure that it can be safely
|
|
// used in
|
|
// a new frame
|
|
// http://julipedia.meroh.net/2011/09/using-vacopy-to-safely-pass-ap.html
|
|
va_list argsDup;
|
|
va_copy(argsDup, vArgs);
|
|
|
|
// Create a copy va_list to reset when we spin
|
|
va_list argsCpy;
|
|
va_copy(argsCpy, argsDup);
|
|
|
|
if (n == 0)
|
|
return strResult;
|
|
|
|
n = n << 4; // Reserve 16 times as much the length of the vrFormat
|
|
|
|
std::unique_ptr<char[]> pFormatted;
|
|
while (1) {
|
|
pFormatted.reset(new char[n + 1]); // +1 for safety margin
|
|
::strncpy(&pFormatted[0], vrFormat.c_str(), n);
|
|
|
|
// We need to restore the variable argument list pointer to the start again
|
|
// before running vsnprintf() more then once
|
|
va_copy(argsDup, argsCpy);
|
|
|
|
nFinal = ::vsnprintf(&pFormatted[0], n, vrFormat.c_str(), argsDup);
|
|
if ((nFinal < 0) || (nFinal >= n))
|
|
n += abs(nFinal - n + 1);
|
|
else
|
|
break;
|
|
}
|
|
|
|
va_end(argsCpy);
|
|
va_end(argsDup);
|
|
|
|
strResult = pFormatted.get();
|
|
|
|
return strResult;
|
|
}
|
|
|
|
//++
|
|
//------------------------------------------------------------------------------------
|
|
// Details: Perform a snprintf format style on a string data. A new string
|
|
// object is
|
|
// created and returned.
|
|
// Type: Static method.
|
|
// Args: vFormat - (R) Format string data instruction.
|
|
// ... - (R) Var list args of any type.
|
|
// Return: CMIUtilString - Number of splits found in the string data.
|
|
// Throws: None.
|
|
//--
|
|
CMIUtilString CMIUtilString::Format(const char *vFormating, ...) {
|
|
va_list args;
|
|
va_start(args, vFormating);
|
|
CMIUtilString strResult = CMIUtilString::FormatPriv(vFormating, args);
|
|
va_end(args);
|
|
|
|
return strResult;
|
|
}
|
|
|
|
//++
|
|
//------------------------------------------------------------------------------------
|
|
// Details: Perform a snprintf format style on a string data. A new string
|
|
// object is
|
|
// created and returned.
|
|
// Type: Static method.
|
|
// Args: vrFormat - (R) Format string data instruction.
|
|
// vArgs - (R) Var list args of any type.
|
|
// Return: CMIUtilString - Number of splits found in the string data.
|
|
// Throws: None.
|
|
//--
|
|
CMIUtilString CMIUtilString::FormatValist(const CMIUtilString &vrFormating,
|
|
va_list vArgs) {
|
|
return CMIUtilString::FormatPriv(vrFormating, vArgs);
|
|
}
|
|
|
|
//++
|
|
//------------------------------------------------------------------------------------
|
|
// Details: Splits string into array of strings using delimiter. If multiple
|
|
// delimiter
|
|
// are found in sequence then they are not added to the list of splits.
|
|
// 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: size_t - Number of splits found in the string data.
|
|
// Throws: None.
|
|
//--
|
|
size_t CMIUtilString::Split(const CMIUtilString &vDelimiter,
|
|
VecString_t &vwVecSplits) const {
|
|
vwVecSplits.clear();
|
|
|
|
if (this->empty() || vDelimiter.empty())
|
|
return 0;
|
|
|
|
const size_t nLen(length());
|
|
size_t nOffset(0);
|
|
do {
|
|
// Find first occurrence which doesn't match to the delimiter
|
|
const size_t nSectionPos(FindFirstNot(vDelimiter, nOffset));
|
|
if (nSectionPos == std::string::npos)
|
|
break;
|
|
|
|
// 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);
|
|
|
|
// Next
|
|
nOffset = nNextDelimiterPos + 1;
|
|
} while (nOffset < nLen);
|
|
|
|
return vwVecSplits.size();
|
|
}
|
|
|
|
//++
|
|
//------------------------------------------------------------------------------------
|
|
// 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 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: size_t - Number of splits found in the string data.
|
|
// Throws: None.
|
|
//--
|
|
size_t CMIUtilString::SplitConsiderQuotes(const CMIUtilString &vDelimiter,
|
|
VecString_t &vwVecSplits) const {
|
|
vwVecSplits.clear();
|
|
|
|
if (this->empty() || vDelimiter.empty())
|
|
return 0;
|
|
|
|
const size_t nLen(length());
|
|
size_t nOffset(0);
|
|
do {
|
|
// Find first occurrence which doesn't match to the delimiter
|
|
const size_t nSectionPos(FindFirstNot(vDelimiter, nOffset));
|
|
if (nSectionPos == std::string::npos)
|
|
break;
|
|
|
|
// 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) {
|
|
vwVecSplits.clear();
|
|
return 0;
|
|
}
|
|
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);
|
|
|
|
// 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.
|
|
// Args: None.
|
|
// Return: CMIUtilString - New version of the string.
|
|
// Throws: None.
|
|
//--
|
|
CMIUtilString CMIUtilString::StripCREndOfLine() const {
|
|
const size_t nPos = rfind('\n');
|
|
if (nPos == std::string::npos)
|
|
return *this;
|
|
|
|
const CMIUtilString strNew(substr(0, nPos));
|
|
|
|
return strNew;
|
|
}
|
|
|
|
//++
|
|
//------------------------------------------------------------------------------------
|
|
// Details: Remove all '\n' from the string and replace with a space. It does
|
|
// not alter
|
|
// *this string.
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: CMIUtilString - New version of the string.
|
|
// Throws: None.
|
|
//--
|
|
CMIUtilString CMIUtilString::StripCRAll() const {
|
|
return FindAndReplace("\n", " ");
|
|
}
|
|
|
|
//++
|
|
//------------------------------------------------------------------------------------
|
|
// Details: Find and replace all matches of a sub string with another string. It
|
|
// does not
|
|
// alter *this string.
|
|
// Type: Method.
|
|
// Args: vFind - (R) The string to look for.
|
|
// vReplaceWith - (R) The string to replace the vFind match.
|
|
// Return: CMIUtilString - New version of the string.
|
|
// Throws: None.
|
|
//--
|
|
CMIUtilString
|
|
CMIUtilString::FindAndReplace(const CMIUtilString &vFind,
|
|
const CMIUtilString &vReplaceWith) const {
|
|
if (vFind.empty() || this->empty())
|
|
return *this;
|
|
|
|
size_t nPos = find(vFind);
|
|
if (nPos == std::string::npos)
|
|
return *this;
|
|
|
|
CMIUtilString strNew(*this);
|
|
while (nPos != std::string::npos) {
|
|
strNew.replace(nPos, vFind.length(), vReplaceWith);
|
|
nPos += vReplaceWith.length();
|
|
nPos = strNew.find(vFind, nPos);
|
|
}
|
|
|
|
return strNew;
|
|
}
|
|
|
|
//++
|
|
//------------------------------------------------------------------------------------
|
|
// Details: Check if *this string is a decimal number.
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: bool - True = yes number, false not a number.
|
|
// Throws: None.
|
|
//--
|
|
bool CMIUtilString::IsNumber() const {
|
|
if (empty())
|
|
return false;
|
|
|
|
if ((at(0) == '-') && (length() == 1))
|
|
return false;
|
|
|
|
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() 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;
|
|
}
|
|
|
|
//++
|
|
//------------------------------------------------------------------------------------
|
|
// 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 extracted from the string.
|
|
// Return: bool - True = yes number, false not a number.
|
|
// Throws: None.
|
|
//--
|
|
bool CMIUtilString::ExtractNumber(MIint64 &vwrNumber) const {
|
|
vwrNumber = 0;
|
|
|
|
if (!IsNumber()) {
|
|
if (ExtractNumberFromHexadecimal(vwrNumber))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
std::stringstream ss(const_cast<CMIUtilString &>(*this));
|
|
ss >> vwrNumber;
|
|
|
|
return true;
|
|
}
|
|
|
|
//++
|
|
//------------------------------------------------------------------------------------
|
|
// Details: Extract the number from the hexadecimal string..
|
|
// Type: Method.
|
|
// Args: vwrNumber - (W) Number extracted from the string.
|
|
// Return: bool - True = yes number, false not a number.
|
|
// Throws: None.
|
|
//--
|
|
bool CMIUtilString::ExtractNumberFromHexadecimal(MIint64 &vwrNumber) const {
|
|
vwrNumber = 0;
|
|
|
|
const size_t nPos = find_first_not_of("xX01234567890ABCDEFabcedf");
|
|
if (nPos != std::string::npos)
|
|
return false;
|
|
|
|
errno = 0;
|
|
const MIuint64 nNum = ::strtoull(this->c_str(), nullptr, 16);
|
|
if (errno == ERANGE)
|
|
return false;
|
|
|
|
vwrNumber = static_cast<MIint64>(nNum);
|
|
|
|
return true;
|
|
}
|
|
|
|
//++
|
|
//------------------------------------------------------------------------------------
|
|
// Details: Determine if the text is all valid alpha numeric characters. Letters
|
|
// can be
|
|
// either upper or lower case.
|
|
// Type: Static method.
|
|
// 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 char *vpText) {
|
|
const size_t len = ::strlen(vpText);
|
|
if (len == 0)
|
|
return false;
|
|
|
|
for (size_t i = 0; i < len; i++, vpText++) {
|
|
const char c = *vpText;
|
|
if (::isalnum((int)c) == 0)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//++
|
|
//------------------------------------------------------------------------------------
|
|
// Details: Check if two strings share equal contents.
|
|
// Type: Method.
|
|
// Args: vrLhs - (R) String A.
|
|
// vrRhs - (R) String B.
|
|
// Return: bool - True = yes equal, false - different.
|
|
// Throws: None.
|
|
//--
|
|
bool CMIUtilString::Compare(const CMIUtilString &vrLhs,
|
|
const CMIUtilString &vrRhs) {
|
|
// Check the sizes match
|
|
if (vrLhs.size() != vrRhs.size())
|
|
return false;
|
|
|
|
return (::strncmp(vrLhs.c_str(), vrRhs.c_str(), vrLhs.size()) == 0);
|
|
}
|
|
|
|
//++
|
|
//------------------------------------------------------------------------------------
|
|
// Details: Remove from either end of *this string the following: " \t\n\v\f\r".
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: CMIUtilString - Trimmed string.
|
|
// Throws: None.
|
|
//--
|
|
CMIUtilString CMIUtilString::Trim() const {
|
|
CMIUtilString strNew(*this);
|
|
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);
|
|
}
|
|
const size_t nPos2 = strNew.find_first_not_of(pWhiteSpace);
|
|
if (nPos2 != std::string::npos) {
|
|
strNew = strNew.substr(nPos2);
|
|
}
|
|
|
|
return strNew;
|
|
}
|
|
|
|
//++
|
|
//------------------------------------------------------------------------------------
|
|
// Details: Remove from either end of *this string the specified character.
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: CMIUtilString - Trimmed string.
|
|
// Throws: None.
|
|
//--
|
|
CMIUtilString CMIUtilString::Trim(const char vChar) const {
|
|
CMIUtilString strNew(*this);
|
|
const size_t nLen = strNew.length();
|
|
if (nLen > 1) {
|
|
if ((strNew[0] == vChar) && (strNew[nLen - 1] == vChar))
|
|
strNew = strNew.substr(1, nLen - 2);
|
|
}
|
|
|
|
return strNew;
|
|
}
|
|
|
|
//++
|
|
//------------------------------------------------------------------------------------
|
|
// Details: Do a printf equivalent for printing a number in binary i.e. "b%llB".
|
|
// Type: Static method.
|
|
// Args: vnDecimal - (R) The number to represent in binary.
|
|
// Return: CMIUtilString - Binary number in text.
|
|
// Throws: None.
|
|
//--
|
|
CMIUtilString CMIUtilString::FormatBinary(const MIuint64 vnDecimal) {
|
|
CMIUtilString strBinaryNumber;
|
|
|
|
const MIuint nConstBits = 64;
|
|
MIuint nRem[nConstBits + 1];
|
|
MIint i = 0;
|
|
MIuint nLen = 0;
|
|
MIuint64 nNum = vnDecimal;
|
|
while ((nNum > 0) && (nLen < nConstBits)) {
|
|
nRem[i++] = nNum % 2;
|
|
nNum = nNum >> 1;
|
|
nLen++;
|
|
}
|
|
char pN[nConstBits + 1];
|
|
MIuint j = 0;
|
|
for (i = nLen; i > 0; --i, j++) {
|
|
pN[j] = '0' + nRem[i - 1];
|
|
}
|
|
pN[j] = 0; // String NUL termination
|
|
|
|
strBinaryNumber = CMIUtilString::Format("0b%s", &pN[0]);
|
|
|
|
return strBinaryNumber;
|
|
}
|
|
|
|
//++
|
|
//------------------------------------------------------------------------------------
|
|
// Details: Remove from a string doubled up characters so only one set left.
|
|
// Characters
|
|
// are only removed if the previous character is already a same
|
|
// character.
|
|
// Type: Method.
|
|
// Args: vChar - (R) The character to search for and remove adjacent
|
|
// duplicates.
|
|
// Return: CMIUtilString - New version of the string.
|
|
// Throws: None.
|
|
//--
|
|
CMIUtilString CMIUtilString::RemoveRepeatedCharacters(const char vChar) {
|
|
return RemoveRepeatedCharacters(0, vChar);
|
|
}
|
|
|
|
//++
|
|
//------------------------------------------------------------------------------------
|
|
// Details: Recursively remove from a string doubled up characters so only one
|
|
// set left.
|
|
// Characters are only removed if the previous character is already a
|
|
// same
|
|
// character.
|
|
// Type: Method.
|
|
// Args: vChar - (R) The character to search for and remove adjacent
|
|
// duplicates.
|
|
// vnPos - Character position in the string.
|
|
// Return: CMIUtilString - New version of the string.
|
|
// Throws: None.
|
|
//--
|
|
CMIUtilString CMIUtilString::RemoveRepeatedCharacters(size_t vnPos,
|
|
const char vChar) {
|
|
const char cQuote = '"';
|
|
|
|
// Look for first quote of two
|
|
const size_t nPos = find(cQuote, vnPos);
|
|
if (nPos == std::string::npos)
|
|
return *this;
|
|
|
|
const size_t nPosNext = nPos + 1;
|
|
if (nPosNext > length())
|
|
return *this;
|
|
|
|
if (at(nPosNext) == cQuote) {
|
|
*this = substr(0, nPos) + substr(nPosNext, length());
|
|
RemoveRepeatedCharacters(nPosNext, vChar);
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
//++
|
|
//------------------------------------------------------------------------------------
|
|
// Details: Is the text in *this string surrounded by quotes.
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: bool - True = Yes string is quoted, false = no quoted.
|
|
// Throws: None.
|
|
//--
|
|
bool CMIUtilString::IsQuoted() const {
|
|
const char cQuote = '"';
|
|
|
|
if (at(0) != cQuote)
|
|
return false;
|
|
|
|
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() 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() 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,
|
|
bool bEscapeQuotes) {
|
|
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 "\\\\";
|
|
case '"':
|
|
if (bEscapeQuotes)
|
|
return "\\\"";
|
|
// fall thru
|
|
default:
|
|
if (::isprint(vChar))
|
|
return Format("%c", vChar);
|
|
else
|
|
return Format("\\x%02" PRIx8, vChar);
|
|
}
|
|
}
|
|
|
|
CMIUtilString
|
|
CMIUtilString::ConvertCharValueToPrintableASCII(char vChar,
|
|
bool bEscapeQuotes) {
|
|
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 "\\\\";
|
|
case '"':
|
|
if (bEscapeQuotes)
|
|
return "\\\"";
|
|
// fall thru
|
|
default:
|
|
if (::isprint(vChar))
|
|
return Format("%c", vChar);
|
|
else
|
|
return CMIUtilString();
|
|
}
|
|
}
|
|
|
|
CMIUtilString CMIUtilString::ConvertToPrintableASCII(const char16_t vChar16,
|
|
bool bEscapeQuotes) {
|
|
if (vChar16 == (char16_t)(char)vChar16) {
|
|
// Convert char16_t to char (if possible)
|
|
CMIUtilString str =
|
|
ConvertCharValueToPrintableASCII((char)vChar16, bEscapeQuotes);
|
|
if (str.length() > 0)
|
|
return str;
|
|
}
|
|
return Format("\\u%02" PRIx8 "%02" PRIx8, (vChar16 >> 8) & 0xff,
|
|
vChar16 & 0xff);
|
|
}
|
|
|
|
CMIUtilString CMIUtilString::ConvertToPrintableASCII(const char32_t vChar32,
|
|
bool bEscapeQuotes) {
|
|
if (vChar32 == (char32_t)(char)vChar32) {
|
|
// Convert char32_t to char (if possible)
|
|
CMIUtilString str =
|
|
ConvertCharValueToPrintableASCII((char)vChar32, bEscapeQuotes);
|
|
if (str.length() > 0)
|
|
return str;
|
|
}
|
|
return Format("\\U%02" PRIx8 "%02" PRIx8 "%02" PRIx8 "%02" PRIx8,
|
|
(vChar32 >> 24) & 0xff, (vChar32 >> 16) & 0xff,
|
|
(vChar32 >> 8) & 0xff, vChar32 & 0xff);
|
|
}
|