1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
/*
* SPDX-License-Identifier: GPL-2.0-or-later
* SPDX-FileName: StringUtils.h
* SPDX-FileContributor: Dmitry Vedenko
*/
#pragma once
#include <algorithm>
#include <cstring>
#include <cwchar>
#include <string>
#include <string_view>
#include <type_traits>
#include <numeric>
#include <wx/string.h>
inline std::size_t StringLength(const char str)
{
return 1;
}
inline std::size_t StringLength(const wchar_t str)
{
return 1;
}
inline std::size_t StringLength(const char* str)
{
return std::strlen(str);
}
inline std::size_t StringLength(const wchar_t* str)
{
return std::wcslen(str);
}
template<typename CharType, size_t N>
std::size_t StringLength (const CharType (&)[N])
{
return N - 1;
}
template<typename StringType>
std::size_t StringLength (const StringType& str)
{
return str.length();
}
template<template<typename, typename...> typename ContainerType, typename ResultType, typename SeparatorType, typename... Rest>
ResultType Join(
const ContainerType<ResultType, Rest...>& container,
const SeparatorType& separator)
{
if (container.empty())
return ResultType {};
const auto sepratorLength = StringLength(separator);
const auto totalSeparatorLength = sepratorLength * (container.size() - 1);
ResultType result;
const auto size = std::accumulate(
container.begin(), container.end(), totalSeparatorLength,
[](size_t size, const ResultType& item)
{ return size + StringLength(item); });
result.reserve(size);
bool first = true;
for (const auto& item : container)
{
if (!first)
result += separator;
result += item;
first = false;
}
return result;
}
STRING_UTILS_API std::string ToLower(const std::string& str);
STRING_UTILS_API std::string ToLower(const std::string_view& str);
STRING_UTILS_API std::string ToLower(const char* str);
STRING_UTILS_API std::wstring ToLower(const std::wstring& str);
STRING_UTILS_API std::wstring ToLower(const std::wstring_view& str);
STRING_UTILS_API std::wstring ToLower(const wchar_t* str);
STRING_UTILS_API wxString ToLower(const wxString& str);
STRING_UTILS_API std::string ToUpper(const std::string& str);
STRING_UTILS_API std::string ToUpper(const std::string_view& str);
STRING_UTILS_API std::string ToUpper(const char* str);
STRING_UTILS_API std::wstring ToUpper(const std::wstring& str);
STRING_UTILS_API std::wstring ToUpper(const std::wstring_view& str);
STRING_UTILS_API std::wstring ToUpper(const wchar_t* str);
STRING_UTILS_API wxString ToUpper(const wxString& str);
namespace details
{
inline const char* begin(const char* str) noexcept
{
return str;
}
inline const char* end(const char* str) noexcept
{
if (str == nullptr)
return nullptr;
return str + StringLength(str);
}
inline const wchar_t* begin(const wchar_t* str) noexcept
{
return str;
}
inline const wchar_t* end(const wchar_t* str) noexcept
{
if (str == nullptr)
return nullptr;
return str + StringLength(str);
}
} // namespace details
template<typename HayType, typename PrefixType>
bool IsPrefixed(
const HayType& hay, const PrefixType& prefix)
{
if (StringLength(hay) < StringLength(prefix))
return false;
using namespace std;
using namespace details;
const auto prefixBegin = begin(prefix);
const auto prefixEnd = end(prefix);
const auto hayBegin = begin(hay);
return std::mismatch(prefixBegin, prefixEnd, hayBegin).first == prefixEnd;
}
template <typename HayType, typename PrefixType>
bool IsPrefixedInsensitive(const HayType& hay, const PrefixType& prefix)
{
return IsPrefixed(ToLower(hay), ToLower(prefix));
}
|