123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421 |
- /**
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0.
- */
- #include <aws/core/utils/StringUtils.h>
- #include <aws/core/utils/memory/stl/AWSStringStream.h>
- #include <algorithm>
- #include <iomanip>
- #include <cstdlib>
- #include <cstdio>
- #include <cstring>
- #include <functional>
- #ifdef _WIN32
- #include <Windows.h>
- #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<Aws::String> StringUtils::Split(const Aws::String& toSplit, char splitOn)
- {
- return Split(toSplit, splitOn, SIZE_MAX, SplitOptions::NOT_SET);
- }
- Aws::Vector<Aws::String> StringUtils::Split(const Aws::String& toSplit, char splitOn, SplitOptions option)
- {
- return Split(toSplit, splitOn, SIZE_MAX, option);
- }
- Aws::Vector<Aws::String> StringUtils::Split(const Aws::String& toSplit, char splitOn, size_t numOfTargetParts)
- {
- return Split(toSplit, splitOn, numOfTargetParts, SplitOptions::NOT_SET);
- }
- Aws::Vector<Aws::String> StringUtils::Split(const Aws::String& toSplit, char splitOn, size_t numOfTargetParts, SplitOptions option)
- {
- Aws::Vector<Aws::String> 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<char>(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<Aws::String> StringUtils::SplitOnLine(const Aws::String& toSplit)
- {
- Aws::StringStream input(toSplit);
- Aws::Vector<Aws::String> 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<int>(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<int>(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<int>(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<int>(output.length()) /*cbMultiByte*/,
- nullptr /*lpDefaultChar*/,
- nullptr /*lpUsedDefaultChar*/);
- if (!result)
- {
- return "";
- }
- output.resize(result);
- return output;
- }
- #endif
|