Logo    
KDWinUtils
Helper library for MFC to Qt migration
Loading...
Searching...
No Matches
kstring.h
Go to the documentation of this file.
1/****************************************************************************
2**
3** This file is part of KDWinutils, KDAB's MFC to Qt migration tool.
4**
5** Copyright (C) 2023 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
6** All rights reserved.
7**
8** This file is intended solely for use by the migration tools and services
9** provided by Klarälvdalens Datakonsult AB.
10**
11** Any other use or distribution of this software that is not otherwise agreed
12** upon in writing and signed by an authorized representative of Klarälvdalens
13** Datakonsult AB, KDAB (USA) LLC, KDAB (Deutschland) GmbH & Co. K.G.,
14** KDAB (France) SAS, KDAB (UK), Ltd., or any future subsidiary of Klarälvdalens
15** Datakonsult AB is hereby prohibited.
16**
17** Contact info@kdab.com if any conditions stated above are unclear to you.
18**
19****************************************************************************/
20
21#pragma once
22
24
25#include <QString>
26
27#ifdef KDWINUTILS_WITHMFC
28#include <afxwin.h>
29#endif // KDWINUTILS_WITHMFC
30
31#include <string>
32
34
44class KDWINUTILS_EXPORT KString : public QString
45{
46public:
49 using QString::QString;
50 /* implicit */ KString(const wchar_t *text);
51 /* implicit */ KString(const QString &str);
52 /* implicit */ KString(QString &&str) noexcept;
53 /* implicit */ KString(const std::wstring_view str);
54
55 // Assignment operators. We redefine a few (and inherit the others),
56 // so that they return KString (and not QString)
57 using QString::operator=;
58 KString &operator=(const char *str);
59 KString &operator=(const wchar_t *str);
60 KString &operator=(const QString &str);
61 KString &operator=(QString &&str) noexcept;
62 KString &operator=(const std::wstring_view str);
63
64 // In-place concatenation
65 using QString::operator+=;
66 KString &operator+=(const char *str);
67 KString &operator+=(const wchar_t *str);
68 KString &operator+=(const QString &str);
69 KString &operator+=(QStringView str);
70
71 /* Inherited operators
72 * This comment exclude those operators to be listed as missing API,
73 * by the ApiComparator tool.
74 *
75 * [ApiComparator: SKIP] bool operator==()
76 * [ApiComparator: SKIP] bool operator!=()
77 * [ApiComparator: SKIP] bool operator>=()
78 * [ApiComparator: SKIP] bool operator<=()
79 * [ApiComparator: SKIP] bool operator>()
80 * [ApiComparator: SKIP] bool operator<()
81 */
82
83#ifdef KDWINUTILS_WITHMFC
84 // CString specific methods, available only on Windows with MFC set
85 explicit KString(const CString &str);
86 CString toCString() const;
87 operator CString() const;
88 KString &operator=(const CString &str);
89 KString &operator+=(const CString &str);
90#endif // KDWINUTILS_WITHMFC
91
100 [[deprecated("Use explicit conversion methods")]] explicit operator const char *() const;
101
102 // MFC API from here on
104
105 template <typename... Ts>
106 KString &Format(const wchar_t *format, Ts &&...args)
107 {
108 *this = FormatString(format, std::forward<Ts>(args)...);
109 return *this;
110 }
111
113 int Compare(const KString &other) const;
114
116 int CompareNoCase(const KString &other) const;
117
119 int Find(const KString &other, int iStart = 0) const;
120
122 bool IsEmpty() const;
123
125 void Empty();
126
133 int GetLength() const;
134
137
140
145 KString Left(int nCount) const;
146
151 KString Right(int nCount) const;
152
155
157 KString &Trim(QChar chTarget);
158
160 KString &Trim(const KString &charsTarget);
161
164
166 KString &TrimLeft(QChar charTarget);
167
169 KString &TrimLeft(const KString &charsTarget);
170
173
175 KString &TrimRight(QChar charTarget);
176
178 KString &TrimRight(const KString &charsTarget);
179
186 int Insert(int iIndex, QChar character);
187
194 int Insert(int iIndex, const KString &string);
195
202 int Remove(QChar chRemove);
203
209 int Collate(const KString &other) const;
210
216 int CollateNoCase(const KString &other) const;
217
224 KString Mid(int iFirst, int nCount = -1) const;
225
232 int Delete(int iIndex, int nCount = 1);
233
242 bool GetEnvironmentVariable(const KString &envVar);
243
250 int FindOneOf(const KString &charSet) const;
251
260 KString Tokenize(const KString &tokens, int &iStart) const;
261
269 int Replace(const KString &before, const KString &after);
270
277 int Replace(QChar before, QChar after);
278
284
290 int ReverseFind(QChar ch);
291
299 KString SpanExcluding(const KString &excludeChars) const;
300
311 KString SpanIncluding(const KString &includeChars) const;
312
313 // Utility methods
315
318 template <typename T, typename... Ts>
319 static QString FormatString(T &&format, Ts... args);
320
321private:
322 // Transform all string types to QByteArray if needed
323 template <typename T>
324 static auto ToByteArray(T &&arg);
325
326 // Transform any QByteArray into a const char * using QByteArray::constData
327 template <typename T>
328 static auto ToConstData(T &&arg);
329};
330
334
335// We have a lot of operator+ overloads available because we inherit from
336// QString. We are also implicitly convertible *from* QString, and *to* QString
337// and CString. This generates a lot of ambiguities, and may be inconvenient to
338// use (because they return QString). So, we define some extra overloads for
339// our own benefit.
340//
341// We still need to be very careful when doing so -- Qt/MFC may be relying on
342// implicit conversions already on certain overloads.
343//
344// For instance: operator+(QString, QLatin1StringView) doesn't exist. Instead,
345// operator+(QString, QString) gets picked, through the implicit conversion of
346// QLatin1String to QString. If we add operator+(KString, QL1SV) we'd make that
347// call ambiguous.
348//
349// Here we try to make our candidates worse than existing ones by making them
350// constrained function templates.
351#define KDWINUTILS_KSTRING_DEFINE_OP_PLUS(StringClass) \
352 template <typename T> \
353 inline std::enable_if_t<std::is_same_v<T, KString>, KString> operator+(T const &s1, StringClass const &s2) \
354 { \
355 return s1 + KString(s2); \
356 } \
357 template <typename T> \
358 inline std::enable_if_t<std::is_same_v<T, KString>, KString> operator+(StringClass const &s1, T const &s2) \
359 { \
360 return KString(s1) + s2; \
361 }
362
367#ifdef KDWINUTILS_WITHMFC
369#endif // KDWINUTILS_WITHMFC
370
371#undef KDWINUTILS_KSTRING_DEFINE_OP_PLUS
372
373template <typename T, typename... Ts>
374QString KString::FormatString(T &&format, Ts... args)
375{
376 // The only way to format using QString::asprintf is to transform into a QByteArray and use constData
377 // The const data has the same lifespan as the QByteArray, so we must keep the QByteArray around before calling
378 // QString::asprintf
379 // 1. Create a tuple with all string parameters changed to a QByteArray if needed
380 auto convertStrings = std::make_tuple(ToByteArray(std::forward<T>(format)), ToByteArray(std::forward<Ts>(args))...);
381
382 // 2. Create another tuple with all string parameters as const char * (they exists because the QByteArray are in
383 // the other tuple)
384 auto convertArgs = std::apply(
385 [&](const auto &...args) {
386 return std::tuple(ToConstData(args)...);
387 },
388 convertStrings);
389
390 // 3. run QString::asprintf with those parameters
391 return std::apply(QString::asprintf, convertArgs);
392}
393
394template <typename T>
395auto KString::ToByteArray(T &&arg)
396{
397 if constexpr (std::is_same_v<QString, std::decay_t<T>>)
398 return arg.toUtf8();
399 else if constexpr (std::is_same_v<KString, std::decay_t<T>>)
400 return arg.toUtf8();
401 else if constexpr (std::is_same_v<const wchar_t *, std::decay_t<T>>)
402 return QString::fromWCharArray(std::forward<T>(arg)).toUtf8();
403 else if constexpr (std::is_same_v<std::wstring, std::decay_t<T>>)
404 return QString::fromStdWString(std::forward<T>(arg)).toUtf8();
405 else if constexpr (std::is_same_v<std::string, std::decay_t<T>>)
406 return QString::fromStdString(std::forward<T>(arg)).toUtf8();
407#ifdef KDWINUTILS_WITHMFC
408 else if constexpr (std::is_same_v<CStringW, std::decay_t<T>>)
409 return QString::fromWCharArray(std::forward<T>(arg), arg.GetLength()).toUtf8();
410 else if constexpr (std::is_same_v<CStringA, std::decay_t<T>>)
411 return (const char *)arg;
412#endif // KDWINUTILS_WITHMFC
413 else
414 return std::forward<T>(arg);
415}
416
417template <typename T>
418auto KString::ToConstData(T &&arg)
419{
420 if constexpr (std::is_same_v<QByteArray, std::decay_t<T>>)
421 return arg.constData();
422 else
423 return std::forward<T>(arg);
424}
425
The KString class provides a Unicode character string.
Definition kstring.h:45
KString Right(int nCount) const
Extracts the rightmost nCount characters from this string object.
int GetLength() const
Returns the number of characters in a KString object.
KString & TrimRight(const KString &charsTarget)
Trims trailing characters from the string.
KString & TrimLeft()
Trims leading whitespace from the string.
KString & operator+=(const CString &str)
KString Tokenize(const KString &tokens, int &iStart) const
Finds the next token in a target string.
KString & operator=(const wchar_t *str)
KString & operator+=(QStringView str)
KString & operator=(const CString &str)
int CollateNoCase(const KString &other) const
Compares two strings according to a localized collation algorithm.
bool GetEnvironmentVariable(const KString &envVar)
Sets the string to the value of the specified environment variable.
int Replace(QChar before, QChar after)
Replaces a character by another character.
KString & TrimRight()
Trims trailing whitespace from the string.
int Collate(const KString &other) const
Compares two strings according to a localized collation algorithm.
KString & TrimLeft(const KString &charsTarget)
Trims leading characters from the string.
void Empty()
Forces a string to have 0 length.
KString(const CString &str)
int Find(const KString &other, int iStart=0) const
Finds a character or substring inside a larger string.
KString SpanExcluding(const KString &excludeChars) const
Extracts characters from the string, starting with the first character, that aren't in the set of cha...
KString & operator+=(const char *str)
KString & operator+=(const wchar_t *str)
KString & MakeReverse()
Reverses the order of the characters in the KString object.
KString & Trim(const KString &charsTarget)
Trims leading and trailing characters from the string.
KString operator+(const KString &s1, const KString &s2)
Concatenate two strings.
int Delete(int iIndex, int nCount=1)
Deletes a character or characters from a string starting with the character at the given index.
KString Mid(int iFirst, int nCount=-1) const
Extracts a substring of length nCount characters from this KString object, starting at position iFirs...
KString & operator=(const char *str)
KString & operator=(QString &&str) noexcept
CString toCString() const
int Insert(int iIndex, QChar character)
Inserts a single character at the given index within the string.
int Compare(const KString &other) const
Compares two strings (case-sensitive).
KString(const QString &str)
KString & Trim(QChar chTarget)
Trims leading and trailing character from the string.
KString SpanIncluding(const KString &includeChars) const
Extracts characters from the string, starting with the first character, that are in the set of charac...
KString & TrimRight(QChar charTarget)
Trims trailing character from the string.
KString & operator=(const std::wstring_view str)
int CompareNoCase(const KString &other) const
Compares two strings (case-insensitive).
int Remove(QChar chRemove)
Removes all instances of the specified character from the string.
KString & MakeLower()
Converts all the characters in this string to lowercase characters.
static QString FormatString(T &&format, Ts... args)
Creates a QString by passing a format string and arguments, like CString::Format.
Definition kstring.h:374
bool IsEmpty() const
Tests whether a CString object contains no characters.
int Insert(int iIndex, const KString &string)
Inserts a substring at the given index within the string.
int FindOneOf(const KString &charSet) const
Searches this string for the first character that matches any character contained in charSet.
KString & MakeUpper()
Converts all the characters in this string to uppercase characters.
KString & Format(const wchar_t *format, Ts &&...args)
Formats the string as sprintf does.
Definition kstring.h:106
int Replace(const KString &before, const KString &after)
Replaces a substring by another substring. Both substrings are null-terminated.
KString(const std::wstring_view str)
KString(QString &&str) noexcept
KString Left(int nCount) const
Extracts the leftmost nCount characters from this string object.
KString & TrimLeft(QChar charTarget)
Trims leading character from the string.
KString & operator=(const QString &str)
KString & operator+=(const QString &str)
KString(const wchar_t *text)
KString & Trim()
Trims leading and trailing whitespace from the string.
int ReverseFind(QChar ch)
Searches this KString object for the last match of a character.
#define KDWINUTILS_EXPORT
Definition kdwinutils_export.h:31
#define KDWINUTILS_BEGIN_NAMESPACE
Definition kdwinutils_global.h:27
#define KDWINUTILS_END_NAMESPACE
Definition kdwinutils_global.h:28
#define KDWINUTILS_KSTRING_DEFINE_OP_PLUS(StringClass)
Definition kstring.h:351