cutelyst 4.3.0
A C++ Web Framework built on top of Qt, using the simple approach of Catalyst (Perl) framework.
validatorbetween.cpp
1/*
2 * SPDX-FileCopyrightText: (C) 2017-2023 Matthias Fehring <mf@huessenbergnetz.de>
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5
6#include "validatorbetween_p.h"
7
8#include <QMetaType>
9
10using namespace Cutelyst;
11
13 QMetaType::Type type,
14 const QVariant &min,
15 const QVariant &max,
16 const ValidatorMessages &messages,
17 const QString &defValKey)
18 : ValidatorRule(*new ValidatorBetweenPrivate(field, type, min, max, messages, defValKey))
19{
20}
21
23
25{
27
28 const QString v = value(params);
29
30 Q_D(const ValidatorBetween);
31
32 if (!v.isEmpty()) {
33 bool ok = false;
34 bool valid = false;
35
36 switch (d->type) {
37 case QMetaType::Char:
39 case QMetaType::Int:
40 case QMetaType::Long:
42 {
43 const qlonglong val = c->locale().toLongLong(v, &ok);
44 if (Q_UNLIKELY(!ok)) {
45 result.errorMessage = parsingError(c);
46 qCWarning(C_VALIDATOR).noquote().nospace()
47 << debugString(c) << " Can not parse input \"" << v
48 << "\" into an integer number";
49 } else {
50 const qlonglong min = d->extractLongLong(c, params, d->min, &ok);
51 if (Q_UNLIKELY(!ok)) {
53 c, static_cast<int>(ValidatorRulePrivate::ErrorType::InvalidMin));
54 qCWarning(C_VALIDATOR).noquote()
55 << "Invalid mininum comparison value:" << d->min;
56 } else {
57 const qlonglong max = d->extractLongLong(c, params, d->max, &ok);
58 if (Q_UNLIKELY(!ok)) {
60 c, static_cast<int>(ValidatorRulePrivate::ErrorType::InvalidMax));
61 qCWarning(C_VALIDATOR).noquote()
62 << "Invalid maximum comparison value:" << d->max;
63 } else {
64 if ((val < min) || (val > max)) {
65 result.errorMessage =
67 QVariantMap{{QStringLiteral("val"), val},
68 {QStringLiteral("min"), min},
69 {QStringLiteral("max"), max}});
70 qCDebug(C_VALIDATOR).noquote()
71 << debugString(c) << val << "is not between" << min << "and" << max;
72 } else {
73 valid = true;
74 }
75 }
76 }
77 }
78 } break;
81 case QMetaType::UInt:
84 {
85 const qulonglong val = v.toULongLong(&ok);
86 if (Q_UNLIKELY(!ok)) {
87 result.errorMessage = parsingError(c);
88 qCWarning(C_VALIDATOR).noquote().nospace()
89 << debugString(c) << " Can not parse input \"" << v
90 << "\" into an unsigned integer number";
91 } else {
92 const qulonglong min = d->extractULongLong(c, params, d->min, &ok);
93 if (Q_UNLIKELY(!ok)) {
95 c, static_cast<int>(ValidatorRulePrivate::ErrorType::InvalidMin));
96 qCWarning(C_VALIDATOR).noquote()
97 << debugString(c) << "Invalid mininum comparison value:" << d->min;
98 } else {
99 const qulonglong max = d->extractULongLong(c, params, d->max, &ok);
100 if (Q_UNLIKELY(!ok)) {
102 c, static_cast<int>(ValidatorRulePrivate::ErrorType::InvalidMax));
103 qCWarning(C_VALIDATOR).noquote()
104 << debugString(c) << "Invalid maximum comparison value:" << d->max;
105 } else {
106 if ((val < min) || (val > max)) {
107 result.errorMessage =
109 QVariantMap{{QStringLiteral("val"), val},
110 {QStringLiteral("min"), min},
111 {QStringLiteral("max"), max}});
112 qCDebug(C_VALIDATOR).noquote()
113 << debugString(c) << val << "is not between" << min << "and" << max;
114 } else {
115 valid = true;
116 }
117 }
118 }
119 }
120 } break;
121 case QMetaType::Float:
123 {
124 const double val = v.toDouble(&ok);
125 if (Q_UNLIKELY(!ok)) {
126 result.errorMessage = parsingError(c);
127 qCWarning(C_VALIDATOR).noquote().nospace()
128 << debugString(c) << " Can not parse input \"" << v
129 << "\" into a floating point number";
130 } else {
131 const double min = d->extractDouble(c, params, d->min, &ok);
132 if (Q_UNLIKELY(!ok)) {
134 c, static_cast<int>(ValidatorRulePrivate::ErrorType::InvalidMin));
135 qCWarning(C_VALIDATOR).noquote()
136 << debugString(c) << "Invalid mininum comparison value:" << d->min;
137 } else {
138 const double max = d->extractDouble(c, params, d->max, &ok);
139 if (Q_UNLIKELY(!ok)) {
141 c, static_cast<int>(ValidatorRulePrivate::ErrorType::InvalidMax));
142 qCWarning(C_VALIDATOR).noquote()
143 << debugString(c) << "Invalid maximum comparison value:" << d->max;
144 } else {
145 if ((val < min) || (val > max)) {
146 result.errorMessage =
148 QVariantMap{{QStringLiteral("val"), val},
149 {QStringLiteral("min"), min},
150 {QStringLiteral("max"), max}});
151 qCDebug(C_VALIDATOR).noquote()
152 << debugString(c) << val << "is not between" << min << "and" << max;
153 } else {
154 valid = true;
155 }
156 }
157 }
158 }
159 } break;
161 {
162 const auto val = static_cast<qlonglong>(v.length());
163 const qlonglong min = d->extractLongLong(c, params, d->min, &ok);
164 if (Q_UNLIKELY(!ok)) {
166 c, static_cast<int>(ValidatorRulePrivate::ErrorType::InvalidMin));
167 qCWarning(C_VALIDATOR).noquote()
168 << debugString(c) << "Invalid mininum comparison value:" << d->min;
169 } else {
170 const qlonglong max = d->extractLongLong(c, params, d->max, &ok);
171 if (Q_UNLIKELY(!ok)) {
173 c, static_cast<int>(ValidatorRulePrivate::ErrorType::InvalidMax));
174 qCWarning(C_VALIDATOR).noquote()
175 << debugString(c) << "Invalid maximum comparison value:" << d->max;
176 } else {
177 if ((val < min) || (val > max)) {
178 result.errorMessage =
180 QVariantMap{{QStringLiteral("val"), val},
181 {QStringLiteral("min"), min},
182 {QStringLiteral("max"), max}});
183 qCDebug(C_VALIDATOR).noquote() << debugString(c) << "String length" << val
184 << "is not between" << min << "and" << max;
185 } else {
186 valid = true;
187 }
188 }
189 }
190 } break;
191 default:
192 qCWarning(C_VALIDATOR).noquote()
193 << debugString(c) << "The comparison type" << d->type << "is not supported";
195 c, static_cast<int>(ValidatorRulePrivate::ErrorType::InvalidType));
196 break;
197 }
198
199 if (valid) {
200 if (d->type != QMetaType::QString) {
201 const QVariant _v = d->valueToNumber(c, v, d->type);
202 if (_v.isValid()) {
203 result.value = _v;
204 } else {
205 result.errorMessage = parsingError(c);
206 }
207 } else {
208 result.value.setValue(v);
209 }
210 }
211 } else {
212 defaultValue(c, &result);
213 }
214
215 return result;
216}
217
219 const QVariant &errorData) const
220{
221 QString error;
222
223 Q_D(const ValidatorBetween);
224
225 const QVariantMap map = errorData.toMap();
226 QString min, max;
227 switch (d->type) {
228 case QMetaType::Char:
229 case QMetaType::Short:
230 case QMetaType::Int:
231 case QMetaType::Long:
234 min = c->locale().toString(map.value(QStringLiteral("min")).toLongLong());
235 max = c->locale().toString(map.value(QStringLiteral("max")).toLongLong());
236 break;
237 case QMetaType::UChar:
239 case QMetaType::UInt:
240 case QMetaType::ULong:
242 min = c->locale().toString(map.value(QStringLiteral("min")).toULongLong());
243 max = c->locale().toString(map.value(QStringLiteral("max")).toULongLong());
244 break;
245 case QMetaType::Float:
247 min = c->locale().toString(map.value(QStringLiteral("min")).toDouble());
248 max = c->locale().toString(map.value(QStringLiteral("max")).toDouble());
249 break;
250 default:
251 return validationDataError(c);
252 }
253
254 const QString _label = label(c);
255
256 if (_label.isEmpty()) {
257 if (d->type == QMetaType::QString) {
258 //: %1 will be replaced by the minimum, %2 by the maximum value
259 //% "The text must be between %1 and %2 characters long."
260 return c->qtTrId("cutelyst-valbetween-genvalerr-string").arg(min, max);
261 } else {
262 //: %1 will be replaced by the minimum, %2 by the maximum value
263 //% "The value must be between %1 and %2."
264 return c->qtTrId("cutelyst-valbetween-genvalerr-num").arg(min, max);
265 }
266 } else {
267 if (d->type == QMetaType::QString) {
268 //: %1 will be replaced by the field label, %2 by the minimum and %3 by the
269 //: maximum value
270 //% "The text in the “%1“ field must be between %2 and %3 characters long."
271 return c->qtTrId("cutelyst-valbetween-genvalerr-string-label").arg(_label, min, max);
272 } else {
273 //: %1 will be replaced by the field label, %2 by the minimum and %3 by the
274 //: maximum value
275 //% "The value in the “%1” field must be between %2 and %3."
276 return c->qtTrId("cutelyst-valbetween-genvalerr-num-label").arg(_label, min, max);
277 }
278 }
279
280 return error;
281}
282
284{
285 const auto errorType = static_cast<ValidatorRulePrivate::ErrorType>(errorData.toInt());
286 const QString _label = label(c);
287
288 if (_label.isEmpty()) {
289 switch (errorType) {
290 case ValidatorRulePrivate::ErrorType::InvalidMin:
291 //% "The minimum comparison value is not valid."
292 return c->qtTrId("cutelyst-validator-genvaldataerr-min");
293 case ValidatorRulePrivate::ErrorType::InvalidType:
294 {
295 Q_D(const ValidatorBetween);
296 QMetaType _type(d->type);
297 //: %1 will be replaced by the name of the comparison type
298 //% "The comparison type %1 is not supported."
299 return c->qtTrId("cutelyst-validator-genvaldataerr-type")
300 .arg(QString::fromLatin1(_type.name()));
301 }
302 case ValidatorRulePrivate::ErrorType::InvalidMax:
303 //% "The maximum comparison value is not valid."
304 return c->qtTrId("cutelyst-validator-genvaldataerr-max");
305 }
306 } else {
307 switch (errorType) {
308 case ValidatorRulePrivate::ErrorType::InvalidMin:
309 //: %1 will be replaced by the field label
310 //% "The minimum comparison value for the “%1” field is not valid."
311 return c->qtTrId("cutelyst-validator-genvaldataerr-min-label").arg(_label);
312 case ValidatorRulePrivate::ErrorType::InvalidType:
313 {
314 Q_D(const ValidatorBetween);
315 QMetaType _type(d->type);
316 //: %1 will be replaced by the type name, %2 will be replaced by the field label
317 //% "The comparison type %1 for the “%2” field is not supported."
318 return c->qtTrId("cutelyst-validator-genvaldataerr-type-label")
319 .arg(QString::fromLatin1(_type.name()), _label);
320 }
321 case ValidatorRulePrivate::ErrorType::InvalidMax:
322 //: %1 will be replaced by the field label
323 //% "The maximum comparison value for the “%1” field is not valid."
324 return c->qtTrId("cutelyst-validator-genvaldataerr-max-label").arg(_label);
325 }
326 }
327
328 return {};
329}
330
332{
333 Q_UNUSED(errorData)
334 Q_D(const ValidatorBetween);
335
336 const QString _label = label(c);
337 if ((d->type == QMetaType::Float) || (d->type == QMetaType::Double)) {
338 if (_label.isEmpty()) {
339 //% "Failed to parse the input value into a floating point number."
340 return c->qtTrId("cutelyst-validator-genparseerr-float");
341 } else {
342 //: %1 will be replaced by the field label
343 //% "Failed to parse the input value for the “%1” field into a "
344 //% "floating point number."
345 return c->qtTrId("cutelyst-validator-genparseerr-float-label").arg(_label);
346 }
347 } else {
348 if (_label.isEmpty()) {
349 //% "Failed to parse the input value into an integer number."
350 return c->qtTrId("cutelyst-validator-genparseerr-int");
351 } else {
352 //: %1 will be replaced by the field label
353 //% "Failed to parse the input value for the “%1” field into an integer number."
354 return c->qtTrId("cutelyst-validator-genparseerr-int-label").arg(_label);
355 }
356 }
357}
The Cutelyst Context.
Definition context.h:42
QLocale locale() const noexcept
Definition context.cpp:460
QString qtTrId(const char *id, int n=-1) const
Definition context.h:656
Checks if a value or text length is between a minimum and maximum value.
ValidatorBetween(const QString &field, QMetaType::Type type, const QVariant &min, const QVariant &max, const ValidatorMessages &messages=ValidatorMessages(), const QString &defValKey=QString())
QString genericValidationError(Context *c, const QVariant &errorData=QVariant()) const override
ValidatorReturnType validate(Context *c, const ParamsMultiMap &params) const override
QString genericParsingError(Context *c, const QVariant &errorData) const override
QString genericValidationDataError(Context *c, const QVariant &errorData) const override
Base class for all validator rules.
QString validationError(Context *c, const QVariant &errorData={}) const
QString label(Context *c) const
QString validationDataError(Context *c, const QVariant &errorData={}) const
void defaultValue(Context *c, ValidatorReturnType *result) const
QString value(const ParamsMultiMap &params) const
QString parsingError(Context *c, const QVariant &errorData={}) const
QString debugString(Context *c) const
The Cutelyst namespace holds all public Cutelyst API.
qlonglong toLongLong(QStringView s, bool *ok) const const
QString toString(QDate date, QLocale::FormatType format) const const
const char * name() const const
QString arg(Args &&... args) const const
QString fromLatin1(QByteArrayView str)
bool isEmpty() const const
qsizetype length() const const
double toDouble(bool *ok) const const
qulonglong toULongLong(bool *ok, int base) const const
bool isValid() const const
void setValue(QVariant &&value)
int toInt(bool *ok) const const
QMap< QString, QVariant > toMap() const const
Stores custom error messages and the input field label.
Contains the result of a single input parameter validation.