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
textutils.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4#include "textutils.h"
5
6#include <QtCore/qcryptographichash.h>
7
9
10/*!
11 \namespace TextUtils
12 \internal
13 \brief Pure string helpers with no dependencies on QDoc driver types.
14
15 TextUtils groups text-manipulation helpers that the IR builders, the
16 template generator, and the legacy generators all need, but that do
17 not touch Node, Tree, Config, or Generator. Keeping them here lets
18 QDocLib components call them without dragging in the rest of QDoc.
19 */
20namespace TextUtils {
21
22/*!
23 \internal
24 Returns the punctuation character for the word at \a wordPosition in a
25 list of \a numberOfWords length. For the last position, returns "."
26 (full stop). For any other word, delegates to comma().
27
28 \sa comma()
29 */
30QString separator(qsizetype wordPosition, qsizetype numberOfWords)
31{
32 static QString terminator = QStringLiteral(".");
33 if (wordPosition == numberOfWords - 1)
34 return terminator;
35 else
36 return comma(wordPosition, numberOfWords);
37}
38
39/*!
40 \internal
41 Returns the inter-item punctuation for a list of \a numberOfWords words
42 at \a wordPosition.
43
44 For a list of length one, returns an empty QString. For a list of length
45 two, returns " and ". For longer lists, returns ", " for early items and
46 ", and " for the item before the last. The last position returns an
47 empty QString; its punctuation is the period returned by separator().
48
49 \sa separator()
50 */
51QString comma(qsizetype wordPosition, qsizetype numberOfWords)
52{
53 if (wordPosition == numberOfWords - 1)
54 return QString();
55 if (numberOfWords == 2)
56 return QStringLiteral(" and ");
57 if (wordPosition == 0 || wordPosition < numberOfWords - 2)
58 return QStringLiteral(", ");
59 return QStringLiteral(", and ");
60}
61
62/*!
63 \brief Returns an ASCII-printable representation of \a str.
64
65 Replaces non-ASCII-printable characters in \a str from a subset of such
66 characters. The subset includes alphanumeric (alnum) characters
67 ([a-zA-Z0-9]), space, punctuation characters, and common symbols. Non-alnum
68 characters in this subset are replaced by a single hyphen. Leading,
69 trailing, and consecutive hyphens are removed, such that the resulting
70 string does not start or end with a hyphen. All characters are converted to
71 lowercase.
72
73 If any character in \a str is non-latin, or latin and not found in the
74 aforementioned subset (e.g. 'ß', 'å', or 'ö'), a hash of \a str is appended
75 to the final string.
76
77 Returns a string that is normalized for use where ASCII-printable strings
78 are required, such as file names or fragment identifiers in URLs.
79*/
80QString asAsciiPrintable(const QString &str)
81{
82 auto legal_ascii = [](const uint value) {
83 const uint start_ascii_subset{ 32 };
84 const uint end_ascii_subset{ 126 };
85
86 return value >= start_ascii_subset && value <= end_ascii_subset;
87 };
88
89 QString result;
90 bool begun = false;
91 bool has_non_alnum_content{ false };
92
93 for (const auto &c : str) {
94 char16_t u = c.unicode();
95 if (!legal_ascii(u))
96 has_non_alnum_content = true;
97 if (u >= 'A' && u <= 'Z')
98 u += 'a' - 'A';
99 if ((u >= 'a' && u <= 'z') || (u >= '0' && u <= '9')) {
100 result += QLatin1Char(u);
101 begun = true;
102 } else if (begun) {
103 result += QLatin1Char('-');
104 begun = false;
105 }
106 }
107 if (result.endsWith(QLatin1Char('-')))
108 result.chop(1);
109
110 if (has_non_alnum_content) {
111 auto title_hash = QString::fromLocal8Bit(
112 QCryptographicHash::hash(str.toUtf8(), QCryptographicHash::Md5).toHex());
113 title_hash.truncate(8);
114 if (!result.isEmpty())
115 result.append(QLatin1Char('-'));
116 result.append(title_hash);
117 }
118
119 return result;
120}
121
122/*!
123 \internal
124 HTML-escapes the ampersand, less-than, greater-than, and double-quote
125 characters in \a str, leaving other characters untouched.
126 */
127QString protect(const QString &str)
128{
129 qsizetype n = str.size();
130 QString marked;
131 marked.reserve(n * 2 + 30);
132 const QChar *data = str.constData();
133 for (int i = 0; i != n; ++i) {
134 switch (data[i].unicode()) {
135 case '&':
136 marked += samp;
137 break;
138 case '<':
139 marked += slt;
140 break;
141 case '>':
142 marked += sgt;
143 break;
144 case '"':
145 marked += squot;
146 break;
147 default:
148 marked += data[i];
149 }
150 }
151 return marked;
152}
153
154} // namespace TextUtils
155
156QT_END_NAMESPACE
Combined button and popup list for selecting options.
Pure string helpers with no dependencies on QDoc driver types.
Definition textutils.h:11
QString protect(const QString &string)
QString asAsciiPrintable(const QString &name)
Returns an ASCII-printable representation of str.
Definition textutils.cpp:80
QString separator(qsizetype wordPosition, qsizetype numberOfWords)
Definition textutils.cpp:30
QString comma(qsizetype wordPosition, qsizetype numberOfWords)
Definition textutils.cpp:51