/** * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ #include #include #include #include #include #include #include #include #ifdef _WIN32 #include #endif using namespace Aws::Utils; void StringUtils::Replace(Aws::String& s, const char* search, const char* replace) { if(!search || !replace) { return; } size_t replaceLength = strlen(replace); size_t searchLength = strlen(search); for (std::size_t pos = 0;; pos += replaceLength) { pos = s.find(search, pos); if (pos == Aws::String::npos) break; s.erase(pos, searchLength); s.insert(pos, replace); } } Aws::String StringUtils::ToLower(const char* source) { Aws::String copy; size_t sourceLength = strlen(source); copy.resize(sourceLength); //appease the latest whims of the VC++ 2017 gods std::transform(source, source + sourceLength, copy.begin(), [](unsigned char c) { return (char)::tolower(c); }); return copy; } Aws::String StringUtils::ToUpper(const char* source) { Aws::String copy; size_t sourceLength = strlen(source); copy.resize(sourceLength); //appease the latest whims of the VC++ 2017 gods std::transform(source, source + sourceLength, copy.begin(), [](unsigned char c) { return (char)::toupper(c); }); return copy; } bool StringUtils::CaselessCompare(const char* value1, const char* value2) { Aws::String value1Lower = ToLower(value1); Aws::String value2Lower = ToLower(value2); return value1Lower == value2Lower; } Aws::Vector StringUtils::Split(const Aws::String& toSplit, char splitOn) { return Split(toSplit, splitOn, SIZE_MAX, SplitOptions::NOT_SET); } Aws::Vector StringUtils::Split(const Aws::String& toSplit, char splitOn, SplitOptions option) { return Split(toSplit, splitOn, SIZE_MAX, option); } Aws::Vector StringUtils::Split(const Aws::String& toSplit, char splitOn, size_t numOfTargetParts) { return Split(toSplit, splitOn, numOfTargetParts, SplitOptions::NOT_SET); } Aws::Vector StringUtils::Split(const Aws::String& toSplit, char splitOn, size_t numOfTargetParts, SplitOptions option) { Aws::Vector returnValues; Aws::StringStream input(toSplit); Aws::String item; while(returnValues.size() < numOfTargetParts - 1 && std::getline(input, item, splitOn)) { if (!item.empty() || option == SplitOptions::INCLUDE_EMPTY_ENTRIES) { returnValues.emplace_back(std::move(item)); } } if (std::getline(input, item, static_cast(EOF))) { if (option != SplitOptions::INCLUDE_EMPTY_ENTRIES) { // Trim all leading delimiters. item.erase(item.begin(), std::find_if(item.begin(), item.end(), [splitOn](int ch) { return ch != splitOn; })); if (!item.empty()) { returnValues.emplace_back(std::move(item)); } } else { returnValues.emplace_back(std::move(item)); } } // To handle the case when there are trailing delimiters. else if (!toSplit.empty() && toSplit.back() == splitOn && option == SplitOptions::INCLUDE_EMPTY_ENTRIES) { returnValues.emplace_back(); } return returnValues; } Aws::Vector StringUtils::SplitOnLine(const Aws::String& toSplit) { Aws::StringStream input(toSplit); Aws::Vector returnValues; Aws::String item; while (std::getline(input, item)) { if (item.size() > 0) { returnValues.push_back(item); } } return returnValues; } Aws::String StringUtils::URLEncode(const char* unsafe) { Aws::StringStream escaped; escaped.fill('0'); escaped << std::hex << std::uppercase; size_t unsafeLength = strlen(unsafe); for (auto i = unsafe, n = unsafe + unsafeLength; i != n; ++i) { char c = *i; if (IsAlnum(c) || c == '-' || c == '_' || c == '.' || c == '~') { escaped << (char)c; } else { //this unsigned char cast allows us to handle unicode characters. escaped << '%' << std::setw(2) << int((unsigned char)c) << std::setw(0); } } return escaped.str(); } Aws::String StringUtils::UTF8Escape(const char* unicodeString, const char* delimiter) { Aws::StringStream escaped; escaped.fill('0'); escaped << std::hex << std::uppercase; size_t unsafeLength = strlen(unicodeString); for (auto i = unicodeString, n = unicodeString + unsafeLength; i != n; ++i) { int c = *i; if (c >= ' ' && c < 127 ) { escaped << (char)c; } else { //this unsigned char cast allows us to handle unicode characters. escaped << delimiter << std::setw(2) << int((unsigned char)c) << std::setw(0); } } return escaped.str(); } Aws::String StringUtils::URLEncode(double unsafe) { char buffer[32]; #if defined(_MSC_VER) && _MSC_VER < 1900 _snprintf_s(buffer, sizeof(buffer), _TRUNCATE, "%g", unsafe); #else snprintf(buffer, sizeof(buffer), "%g", unsafe); #endif return StringUtils::URLEncode(buffer); } Aws::String StringUtils::URLDecode(const char* safe) { Aws::String unescaped; for (; *safe; safe++) { switch(*safe) { case '%': { int hex = 0; auto ch = *++safe; if (ch >= '0' && ch <= '9') { hex = (ch - '0') * 16; } else if (ch >= 'A' && ch <= 'F') { hex = (ch - 'A' + 10) * 16; } else if (ch >= 'a' && ch <= 'f') { hex = (ch - 'a' + 10) * 16; } else { unescaped.push_back('%'); if (ch == 0) { return unescaped; } unescaped.push_back(ch); break; } ch = *++safe; if (ch >= '0' && ch <= '9') { hex += (ch - '0'); } else if (ch >= 'A' && ch <= 'F') { hex += (ch - 'A' + 10); } else if (ch >= 'a' && ch <= 'f') { hex += (ch - 'a' + 10); } else { unescaped.push_back('%'); unescaped.push_back(*(safe - 1)); if (ch == 0) { return unescaped; } unescaped.push_back(ch); break; } unescaped.push_back(char(hex)); break; } case '+': unescaped.push_back(' '); break; default: unescaped.push_back(*safe); break; } } return unescaped; } static bool IsSpace(int ch) { if (ch < -1 || ch > 255) { return false; } return ::isspace(ch) != 0; } Aws::String StringUtils::LTrim(const char* source) { Aws::String copy(source); copy.erase(copy.begin(), std::find_if(copy.begin(), copy.end(), [](int ch) { return !IsSpace(ch); })); return copy; } // trim from end Aws::String StringUtils::RTrim(const char* source) { Aws::String copy(source); copy.erase(std::find_if(copy.rbegin(), copy.rend(), [](int ch) { return !IsSpace(ch); }).base(), copy.end()); return copy; } // trim from both ends Aws::String StringUtils::Trim(const char* source) { return LTrim(RTrim(source).c_str()); } long long StringUtils::ConvertToInt64(const char* source) { if(!source) { return 0; } #ifdef __ANDROID__ return atoll(source); #else return std::atoll(source); #endif // __ANDROID__ } long StringUtils::ConvertToInt32(const char* source) { if (!source) { return 0; } return std::atol(source); } bool StringUtils::ConvertToBool(const char* source) { if(!source) { return false; } Aws::String strValue = ToLower(source); if(strValue == "true" || strValue == "1") { return true; } return false; } double StringUtils::ConvertToDouble(const char* source) { if(!source) { return 0.0; } return std::strtod(source, NULL); } #ifdef _WIN32 Aws::WString StringUtils::ToWString(const char* source) { const auto len = static_cast(std::strlen(source)); Aws::WString outString; outString.resize(len); // there is no way UTF-16 would require _more_ code-points than UTF-8 for the _same_ string const auto result = MultiByteToWideChar(CP_UTF8 /*CodePage*/, 0 /*dwFlags*/, source /*lpMultiByteStr*/, len /*cbMultiByte*/, &outString[0] /*lpWideCharStr*/, static_cast(outString.length())/*cchWideChar*/); if (!result) { return L""; } outString.resize(result); return outString; } Aws::String StringUtils::FromWString(const wchar_t* source) { const auto len = static_cast(std::wcslen(source)); Aws::String output; if (int requiredSizeInBytes = WideCharToMultiByte(CP_UTF8 /*CodePage*/, 0 /*dwFlags*/, source /*lpWideCharStr*/, len /*cchWideChar*/, nullptr /*lpMultiByteStr*/, 0 /*cbMultiByte*/, nullptr /*lpDefaultChar*/, nullptr /*lpUsedDefaultChar*/)) { output.resize(requiredSizeInBytes); } const auto result = WideCharToMultiByte(CP_UTF8 /*CodePage*/, 0 /*dwFlags*/, source /*lpWideCharStr*/, len /*cchWideChar*/, &output[0] /*lpMultiByteStr*/, static_cast(output.length()) /*cbMultiByte*/, nullptr /*lpDefaultChar*/, nullptr /*lpUsedDefaultChar*/); if (!result) { return ""; } output.resize(result); return output; } #endif