Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qlocale_icu.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:critical reason:data-parser
4
5#include "qglobal.h"
6#include "qdebug.h"
7#include "qlocale_p.h"
8#include "qmutex.h"
9
10#include "unicode/uloc.h"
11#include "unicode/ustring.h"
12
13QT_BEGIN_NAMESPACE
14
15static_assert(std::is_same_v<UChar, char16_t>,
16 "Hmm... in C++ mode, ICU's UChar ought to be char16_t");
17
18namespace QtIcuPrivate {
19
20enum class CaseConversion : bool { Upper, Lower };
21
22static bool qt_u_strToCase(const QString &str, QString *out, const char *localeID,
23 CaseConversion conv)
24{
25 Q_ASSERT(out);
26
27 int32_t size = str.size();
28 size += size >> 2; // add 25% for possible expansions
29 QString result(size, Qt::Uninitialized);
30
31 UErrorCode status = U_ZERO_ERROR;
32
33 const auto caseFunc = [conv] (auto&&...args) {
34 // try to be a completely transparent wrapper:
35 using R [[maybe_unused]] = decltype(u_strToUpper(std::forward<decltype(args)>(args)...));
36 switch (conv) {
38 return u_strToUpper(std::forward<decltype(args)>(args)...);
40 return u_strToLower(std::forward<decltype(args)>(args)...);
41 };
42 Q_UNREACHABLE_RETURN(R{0});
43 };
44
45 size = caseFunc(result.data_ptr().data(), result.size(),
46 str.data_ptr().data(), str.size(),
47 localeID, &status);
48
49 if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR)
50 return false;
51
52 if (size < result.size()) {
53 result.resize(size);
54 } else if (size > result.size()) {
55 // the resulting string is larger than our source string
56 result.resize(size);
57
58 status = U_ZERO_ERROR;
59 size = caseFunc(result.data_ptr().data(), result.size(),
60 str.data_ptr().data(), str.size(),
61 localeID, &status);
62
63 if (U_FAILURE(status))
64 return false;
65
66 // if the sizes don't match now, we give up.
67 if (size != result.size())
68 return false;
69 }
70
71 *out = std::move(result);
72 return true;
73}
74
75} // namespace QtIcuPrivate
76
77QString QLocalePrivate::toUpper(const QString &str, bool *ok) const
78{
79 Q_ASSERT(ok);
80 using namespace QtIcuPrivate;
81 QString out;
82 *ok = qt_u_strToCase(str, &out, bcp47Name('_'), CaseConversion::Upper);
83 return out;
84}
85
86QString QLocalePrivate::toLower(const QString &str, bool *ok) const
87{
88 Q_ASSERT(ok);
89 using namespace QtIcuPrivate;
90 QString out;
91 *ok = qt_u_strToCase(str, &out, bcp47Name('_'), CaseConversion::Lower);
92 return out;
93}
94
95QT_END_NAMESPACE
static bool qt_u_strToCase(const QString &str, QString *out, const char *localeID, CaseConversion conv)