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;
179 auto processKeyPair = [&] {
181 if ((data - from) == 0) {
182 if (!key.isEmpty()) {
187 skipUtf8 ? QString::fromLatin1(from, data - from)
188 : QString::fromUtf8(from, data - from));
190 }
else if ((data - from) > 0) {
191 ret.insert(skipUtf8 ? QString::fromLatin1(from, data - from)
192 : QString::fromUtf8(from, data - from),
197 for (
int i = 0; i < len; ++i, ++outlen) {
198 const char c = inputPtr[i];
199 if (c ==
'%' && i + 2 < len) {
200 int a = inputPtr[++i];
201 int b = inputPtr[++i];
203 if (a >=
'0' && a <=
'9')
205 else if (a >=
'a' && a <=
'f')
207 else if (a >=
'A' && a <=
'F')
210 if (b >=
'0' && b <=
'9')
212 else if (b >=
'a' && b <=
'f')
214 else if (b >=
'A' && b <=
'F')
217 *data++ = (char) ((a << 4) | b);
219 }
else if (c ==
'+') {
221 }
else if (c ==
'=') {
222 key = skipUtf8 ? QString::fromLatin1(from, data - from)
223 : QString::fromUtf8(from, data - from);
227 }
else if (c ==
'&') {
243QString Utils::decodePercentEncoding(QByteArray *ba)
249 char *data = ba->data();
250 const char *inputPtr = data;
252 int len = ba->length();
253 bool skipUtf8 =
true;
255 for (
int i = 0; i < len; ++i, ++outlen) {
256 const char c = inputPtr[i];
257 if (c ==
'%' && i + 2 < len) {
258 int a = inputPtr[++i];
259 int b = inputPtr[++i];
261 if (a >=
'0' && a <=
'9')
263 else if (a >=
'a' && a <=
'f')
265 else if (a >=
'A' && a <=
'F')
268 if (b >=
'0' && b <=
'9')
270 else if (b >=
'a' && b <=
'f')
272 else if (b >=
'A' && b <=
'F')
275 *data++ = (char) ((a << 4) | b);
277 }
else if (c ==
'+') {
285 return QString::fromLatin1(ba->data(), outlen);
287 return QString::fromUtf8(ba->data(), outlen);
293 QList<std::pair<QString, QString>> parts;
298 for (
const QChar ch : str) {
299 if (ch >= u
'0' && ch <= u
'9') {
300 if (digitPart.isEmpty() && unitPart.isEmpty()) {
302 digitPart.append(ch);
303 }
else if (digitPart.isEmpty() && !unitPart.isEmpty()) {
307 }
else if (!digitPart.isEmpty() && unitPart.isEmpty()) {
309 digitPart.append(ch);
310 }
else if (!digitPart.isEmpty() && !unitPart.isEmpty()) {
312 parts.emplace_back(digitPart, unitPart);
315 digitPart.append(ch);
317 }
else if ((ch >= u
'a' && ch <= u
'z') || ch == u
'M') {
318 if (digitPart.isEmpty() && unitPart.isEmpty()) {
322 }
else if (digitPart.isEmpty() && !unitPart.isEmpty()) {
326 }
else if (!digitPart.isEmpty() && unitPart.isEmpty()) {
329 }
else if (!digitPart.isEmpty() && !unitPart.isEmpty()) {
341 return std::chrono::microseconds::zero();
344 if (!digitPart.isEmpty()) {
345 parts.emplace_back(digitPart, unitPart);
352 return std::chrono::microseconds::zero();
355 std::chrono::microseconds ms = std::chrono::microseconds::zero();
357 for (
const std::pair<QString, QString> &p : parts) {
359 const qulonglong dur = p.first.toULongLong(&_ok);
365 if (p.second == u
"usec" || p.second == u
"us") {
366 ms += std::chrono::microseconds{dur};
367 }
else if (p.second == u
"msec" || p.second == u
"ms") {
368 ms += std::chrono::milliseconds{dur};
369 }
else if (p.second == u
"seconds" || p.second == u
"second" || p.second == u
"sec" ||
370 p.second == u
"s" || p.second.isEmpty()) {
371 ms += std::chrono::seconds{dur};
372 }
else if (p.second == u
"minutes" || p.second == u
"minute" || p.second == u
"min" ||
374 ms += std::chrono::minutes{dur};
375 }
else if (p.second == u
"hours" || p.second == u
"hour" || p.second == u
"hr" ||
377 ms += std::chrono::hours{dur};
378 }
else if (p.second == u
"days" || p.second == u
"day" || p.second == u
"d") {
379 ms += std::chrono::days{dur};
380 }
else if (p.second == u
"weeks" || p.second == u
"week" || p.second == u
"w") {
381 ms += std::chrono::weeks{dur};
382 }
else if (p.second == u
"months" || p.second == u
"month" || p.second == u
"M") {
383 ms += std::chrono::months{dur};
384 }
else if (p.second == u
"years" || p.second == u
"year" || p.second == u
"y") {
385 ms += std::chrono::years{dur};
396 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.