12QByteArray buildTableDivision(
const QVector<int> &columnsSize)
15 QTextStream out(&buffer, QTextStream::WriteOnly);
16 for (
int i = 0; i < columnsSize.size(); ++i) {
22 out << QByteArray().fill(
'-', columnsSize[i] + 2).data();
29QByteArray Utils::buildTable(
const QVector<QStringList> &table,
30 const QStringList &headers,
34 QVector<int> columnsSize;
36 if (!headers.isEmpty()) {
37 for (
const QString &header : headers) {
38 columnsSize.push_back(header.size());
41 for (
const QStringList &rows : table) {
42 if (columnsSize.empty()) {
43 for (
const QString &row : rows) {
44 columnsSize.push_back(row.size());
46 }
else if (rows.size() != columnsSize.size()) {
47 qFatal(
"Incomplete table");
52 for (
const QStringList &row : table) {
53 if (row.size() > columnsSize.size()) {
54 qFatal(
"Incomplete table");
58 for (
int i = 0; i < row.size(); ++i) {
59 columnsSize[i] = qMax(columnsSize[i], row[i].size());
64 QTextStream out(&buffer, QTextStream::WriteOnly);
66 out.setFieldAlignment(QTextStream::AlignLeft);
67 QByteArray div = buildTableDivision(columnsSize);
69 if (!title.isEmpty()) {
76 if (!headers.isEmpty()) {
78 for (
int i = 0; i < headers.size(); ++i) {
81 out.setFieldWidth(columnsSize[i]);
93 for (
const QStringList &row : table) {
95 for (
int i = 0; i < row.size(); ++i) {
98 out.setFieldWidth(columnsSize[i]);
101 out.setFieldWidth(0);
113QString Utils::decodePercentEncoding(QString *s)
119 QByteArray ba = s->toLatin1();
121 char *data = ba.data();
122 const char *inputPtr = data;
124 const int len = ba.length();
125 bool skipUtf8 =
true;
127 for (
int i = 0; i < len; ++i, ++outlen) {
128 const char c = inputPtr[i];
129 if (c ==
'%' && i + 2 < len) {
130 int a = inputPtr[++i];
131 int b = inputPtr[++i];
133 if (a >=
'0' && a <=
'9')
135 else if (a >=
'a' && a <=
'f')
137 else if (a >=
'A' && a <=
'F')
140 if (b >=
'0' && b <=
'9')
142 else if (b >=
'a' && b <=
'f')
144 else if (b >=
'A' && b <=
'F')
147 *data++ = (char) ((a << 4) | b);
149 }
else if (c ==
'+') {
160 return QString::fromUtf8(ba.data(), outlen);
172 const char *inputPtr = data;
175 bool skipUtf8 =
true;
178 auto processKeyPair = [&] {
180 if ((data - from) == 0) {
181 if (!key.isEmpty()) {
186 skipUtf8 ? QString::fromLatin1(from, data - from)
187 : QString::fromUtf8(from, data - from));
189 }
else if ((data - from) > 0) {
190 ret.insert(skipUtf8 ? QString::fromLatin1(from, data - from)
191 : QString::fromUtf8(from, data - from),
196 for (
int i = 0; i < len; ++i) {
197 const char c = inputPtr[i];
198 if (c ==
'%' && i + 2 < len) {
199 int a = inputPtr[++i];
200 int b = inputPtr[++i];
202 if (a >=
'0' && a <=
'9')
204 else if (a >=
'a' && a <=
'f')
206 else if (a >=
'A' && a <=
'F')
209 if (b >=
'0' && b <=
'9')
211 else if (b >=
'a' && b <=
'f')
213 else if (b >=
'A' && b <=
'F')
216 *data++ = (char) ((a << 4) | b);
218 }
else if (c ==
'+') {
220 }
else if (c ==
'=') {
221 key = skipUtf8 ? QString::fromLatin1(from, data - from)
222 : QString::fromUtf8(from, data - from);
226 }
else if (c ==
'&') {
242QString Utils::decodePercentEncoding(QByteArray *ba)
248 char *data = ba->data();
249 const char *inputPtr = data;
251 int len = ba->length();
252 bool skipUtf8 =
true;
254 for (
int i = 0; i < len; ++i, ++outlen) {
255 const char c = inputPtr[i];
256 if (c ==
'%' && i + 2 < len) {
257 int a = inputPtr[++i];
258 int b = inputPtr[++i];
260 if (a >=
'0' && a <=
'9')
262 else if (a >=
'a' && a <=
'f')
264 else if (a >=
'A' && a <=
'F')
267 if (b >=
'0' && b <=
'9')
269 else if (b >=
'a' && b <=
'f')
271 else if (b >=
'A' && b <=
'F')
274 *data++ = (char) ((a << 4) | b);
276 }
else if (c ==
'+') {
284 return QString::fromLatin1(ba->data(), outlen);
286 return QString::fromUtf8(ba->data(), outlen);
292 QList<std::pair<QString, QString>> parts;
297 for (
const QChar ch : str) {
298 if (ch >= u
'0' && ch <= u
'9') {
299 if (digitPart.isEmpty() && unitPart.isEmpty()) {
301 digitPart.append(ch);
302 }
else if (digitPart.isEmpty() && !unitPart.isEmpty()) {
306 }
else if (!digitPart.isEmpty() && unitPart.isEmpty()) {
308 digitPart.append(ch);
309 }
else if (!digitPart.isEmpty() && !unitPart.isEmpty()) {
311 parts.emplace_back(digitPart, unitPart);
314 digitPart.append(ch);
316 }
else if ((ch >= u
'a' && ch <= u
'z') || ch == u
'M') {
317 if (digitPart.isEmpty() && unitPart.isEmpty()) {
321 }
else if (digitPart.isEmpty() && !unitPart.isEmpty()) {
325 }
else if (!digitPart.isEmpty() && unitPart.isEmpty()) {
328 }
else if (!digitPart.isEmpty() && !unitPart.isEmpty()) {
340 return std::chrono::microseconds::zero();
343 if (!digitPart.isEmpty()) {
344 parts.emplace_back(digitPart, unitPart);
351 return std::chrono::microseconds::zero();
354 std::chrono::microseconds ms = std::chrono::microseconds::zero();
356 for (
const std::pair<QString, QString> &p : parts) {
358 const qulonglong dur = p.first.toULongLong(&_ok);
364 if (p.second == u
"usec" || p.second == u
"us") {
365 ms += std::chrono::microseconds{dur};
366 }
else if (p.second == u
"msec" || p.second == u
"ms") {
367 ms += std::chrono::milliseconds{dur};
368 }
else if (p.second == u
"seconds" || p.second == u
"second" || p.second == u
"sec" ||
369 p.second == u
"s" || p.second.isEmpty()) {
370 ms += std::chrono::seconds{dur};
371 }
else if (p.second == u
"minutes" || p.second == u
"minute" || p.second == u
"min" ||
373 ms += std::chrono::minutes{dur};
374 }
else if (p.second == u
"hours" || p.second == u
"hour" || p.second == u
"hr" ||
376 ms += std::chrono::hours{dur};
377 }
else if (p.second == u
"days" || p.second == u
"day" || p.second == u
"d") {
378 ms += std::chrono::days{dur};
379 }
else if (p.second == u
"weeks" || p.second == u
"week" || p.second == u
"w") {
380 ms += std::chrono::weeks{dur};
381 }
else if (p.second == u
"months" || p.second == u
"month" || p.second == u
"M") {
382 ms += std::chrono::months{dur};
383 }
else if (p.second == u
"years" || p.second == u
"year" || p.second == u
"y") {
384 ms += std::chrono::years{dur};
395 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.