16QByteArray buildTableDivision(
const QVector<int> &columnsSize)
19 QTextStream out(&buffer, QTextStream::WriteOnly);
20 for (
int i = 0; i < columnsSize.size(); ++i) {
26 out << QByteArray().fill(
'-', columnsSize[i] + 2).data();
35QByteArray Utils::buildTable(
const QVector<QStringList> &table,
36 const QStringList &headers,
40 QVector<int> columnsSize;
42 if (!headers.isEmpty()) {
43 std::ranges::transform(headers, std::back_inserter(columnsSize), [](
const QString &header) {
47 for (
const QStringList &rows : table) {
48 if (columnsSize.empty()) {
49 std::ranges::transform(rows,
50 std::back_inserter(columnsSize),
51 [](
const QString &row) {
return row.size(); });
52 }
else if (rows.size() != columnsSize.size()) {
53 qFatal(
"Incomplete table");
58 for (
const QStringList &row : table) {
59 if (row.size() > columnsSize.size()) {
60 qFatal(
"Incomplete table");
63 for (
int i = 0; i < row.size(); ++i) {
64 columnsSize[i] = qMax(columnsSize[i], row[i].size());
69 QTextStream out(&buffer, QTextStream::WriteOnly);
71 out.setFieldAlignment(QTextStream::AlignLeft);
72 QByteArray div = buildTableDivision(columnsSize);
74 if (!title.isEmpty()) {
81 if (!headers.isEmpty()) {
83 for (
int i = 0; i < headers.size(); ++i) {
86 out.setFieldWidth(columnsSize[i]);
98 for (
const QStringList &row : table) {
100 for (
int i = 0; i < row.size(); ++i) {
103 out.setFieldWidth(columnsSize[i]);
106 out.setFieldWidth(0);
118QString Utils::decodePercentEncoding(QString *s)
124 QByteArray ba = s->toLatin1();
126 char *data = ba.data();
127 const char *inputPtr = data;
129 const int len = ba.length();
130 bool skipUtf8 =
true;
132 for (
int i = 0; i < len; ++i, ++outlen) {
133 const char c = inputPtr[i];
134 if (c ==
'%' && i + 2 < len) {
135 int a =
static_cast<int>(
static_cast<unsigned char>(inputPtr[++i]));
136 int b =
static_cast<int>(
static_cast<unsigned char>(inputPtr[++i]));
138 if (a >=
'0' && a <=
'9') {
140 }
else if (a >=
'a' && a <=
'f') {
142 }
else if (a >=
'A' && a <=
'F') {
146 if (b >=
'0' && b <=
'9') {
148 }
else if (b >=
'a' && b <=
'f') {
150 }
else if (b >=
'A' && b <=
'F') {
154 *data++ = (char) ((a << 4) | b);
156 }
else if (c ==
'+') {
167 return QString::fromUtf8(ba.data(), outlen);
179 const char *inputPtr = data;
182 bool skipUtf8 =
true;
185 auto processKeyPair = [&] {
187 if ((data - from) == 0) {
188 if (!key.isEmpty()) {
193 skipUtf8 ? QString::fromLatin1(from, data - from)
194 : QString::fromUtf8(from, data - from));
196 }
else if ((data - from) > 0) {
197 ret.insert(skipUtf8 ? QString::fromLatin1(from, data - from)
198 : QString::fromUtf8(from, data - from),
203 for (
int i = 0; i < len; ++i) {
204 const char c = inputPtr[i];
205 if (c ==
'%' && i + 2 < len) {
206 int a =
static_cast<int>(
static_cast<unsigned char>(inputPtr[++i]));
207 int b =
static_cast<int>(
static_cast<unsigned char>(inputPtr[++i]));
209 if (a >=
'0' && a <=
'9') {
211 }
else if (a >=
'a' && a <=
'f') {
213 }
else if (a >=
'A' && a <=
'F') {
217 if (b >=
'0' && b <=
'9') {
219 }
else if (b >=
'a' && b <=
'f') {
221 }
else if (b >=
'A' && b <=
'F') {
225 *data++ = (char) ((a << 4) | b);
227 }
else if (c ==
'+') {
229 }
else if (c ==
'=') {
230 key = skipUtf8 ? QString::fromLatin1(from, data - from)
231 : QString::fromUtf8(from, data - from);
235 }
else if (c ==
'&') {
251QString Utils::decodePercentEncoding(QByteArray *ba)
257 char *data = ba->data();
258 const char *inputPtr = data;
260 int len = ba->length();
261 bool skipUtf8 =
true;
263 for (
int i = 0; i < len; ++i, ++outlen) {
264 const char c = inputPtr[i];
265 if (c ==
'%' && i + 2 < len) {
266 int a =
static_cast<int>(
static_cast<unsigned char>(inputPtr[++i]));
267 int b =
static_cast<int>(
static_cast<unsigned char>(inputPtr[++i]));
269 if (a >=
'0' && a <=
'9') {
271 }
else if (a >=
'a' && a <=
'f') {
273 }
else if (a >=
'A' && a <=
'F') {
277 if (b >=
'0' && b <=
'9') {
279 }
else if (b >=
'a' && b <=
'f') {
281 }
else if (b >=
'A' && b <=
'F') {
285 *data++ = (char) ((a << 4) | b);
287 }
else if (c ==
'+') {
295 return QString::fromLatin1(ba->data(), outlen);
297 return QString::fromUtf8(ba->data(), outlen);
303 QList<std::pair<QString, QString>> parts;
308 for (
const QChar ch : str) {
309 if (ch >= u
'0' && ch <= u
'9') {
310 if (digitPart.isEmpty() && unitPart.isEmpty()) {
312 digitPart.append(ch);
313 }
else if (digitPart.isEmpty() && !unitPart.isEmpty()) {
317 }
else if (!digitPart.isEmpty() && unitPart.isEmpty()) {
319 digitPart.append(ch);
320 }
else if (!digitPart.isEmpty() && !unitPart.isEmpty()) {
322 parts.emplace_back(digitPart, unitPart);
325 digitPart.append(ch);
327 }
else if ((ch >= u
'a' && ch <= u
'z') || ch == u
'M') {
328 if (digitPart.isEmpty() && unitPart.isEmpty()) {
332 }
else if (digitPart.isEmpty() && !unitPart.isEmpty()) {
336 }
else if (!digitPart.isEmpty() && unitPart.isEmpty()) {
339 }
else if (!digitPart.isEmpty() && !unitPart.isEmpty()) {
351 return std::chrono::microseconds::zero();
354 if (!digitPart.isEmpty()) {
355 parts.emplace_back(digitPart, unitPart);
362 return std::chrono::microseconds::zero();
365 std::chrono::microseconds ms = std::chrono::microseconds::zero();
367 for (
const std::pair<QString, QString> &p : parts) {
369 const qulonglong dur = p.first.toULongLong(&_ok);
375 if (p.second == u
"usec" || p.second == u
"us") {
376 ms += std::chrono::microseconds{dur};
377 }
else if (p.second == u
"msec" || p.second == u
"ms") {
378 ms += std::chrono::milliseconds{dur};
379 }
else if (p.second == u
"seconds" || p.second == u
"second" || p.second == u
"sec" ||
380 p.second == u
"s" || p.second.isEmpty()) {
381 ms += std::chrono::seconds{dur};
382 }
else if (p.second == u
"minutes" || p.second == u
"minute" || p.second == u
"min" ||
384 ms += std::chrono::minutes{dur};
385 }
else if (p.second == u
"hours" || p.second == u
"hour" || p.second == u
"hr" ||
387 ms += std::chrono::hours{dur};
388 }
else if (p.second == u
"days" || p.second == u
"day" || p.second == u
"d") {
389 ms += std::chrono::days{dur};
390 }
else if (p.second == u
"weeks" || p.second == u
"week" || p.second == u
"w") {
391 ms += std::chrono::weeks{dur};
392 }
else if (p.second == u
"months" || p.second == u
"month" || p.second == u
"M") {
393 ms += std::chrono::months{dur};
394 }
else if (p.second == u
"years" || p.second == u
"year" || p.second == u
"y") {
395 ms += std::chrono::years{dur};
406 return std::chrono::microseconds::zero();
QMultiMap< QString, QString > ParamsMultiMap
CUTELYST_EXPORT std::chrono::microseconds durationFromString(QStringView str, bool *ok=nullptr)
The Cutelyst namespace holds all public Cutelyst API.