cutelyst 5.0.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-2025 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 =
51 ValidatorBetweenPrivate::extractLongLong(c, params, d->min, &ok);
52 if (Q_UNLIKELY(!ok)) {
54 c, static_cast<int>(ValidatorRulePrivate::ErrorType::InvalidMin));
55 qCWarning(C_VALIDATOR).noquote()
56 << "Invalid mininum comparison value:" << d->min;
57 } else {
58 const qlonglong max =
59 ValidatorBetweenPrivate::extractLongLong(c, params, d->max, &ok);
60 if (Q_UNLIKELY(!ok)) {
62 c, static_cast<int>(ValidatorRulePrivate::ErrorType::InvalidMax));
63 qCWarning(C_VALIDATOR).noquote()
64 << "Invalid maximum comparison value:" << d->max;
65 } else {
66 if ((val < min) || (val > max)) {
67 result.errorMessage =
69 QVariantMap{{QStringLiteral("val"), val},
70 {QStringLiteral("min"), min},
71 {QStringLiteral("max"), max}});
72 qCDebug(C_VALIDATOR).noquote()
73 << debugString(c) << val << "is not between" << min << "and" << max;
74 } else {
75 valid = true;
76 }
77 }
78 }
79 }
80 } break;
83 case QMetaType::UInt:
86 {
87 const qulonglong val = v.toULongLong(&ok);
88 if (Q_UNLIKELY(!ok)) {
89 result.errorMessage = parsingError(c);
90 qCWarning(C_VALIDATOR).noquote().nospace()
91 << debugString(c) << " Can not parse input \"" << v
92 << "\" into an unsigned integer number";
93 } else {
94 const qulonglong min =
95 ValidatorBetweenPrivate::extractULongLong(c, params, d->min, &ok);
96 if (Q_UNLIKELY(!ok)) {
98 c, static_cast<int>(ValidatorRulePrivate::ErrorType::InvalidMin));
99 qCWarning(C_VALIDATOR).noquote()
100 << debugString(c) << "Invalid mininum comparison value:" << d->min;
101 } else {
102 const qulonglong max =
103 ValidatorBetweenPrivate::extractULongLong(c, params, d->max, &ok);
104 if (Q_UNLIKELY(!ok)) {
106 c, static_cast<int>(ValidatorRulePrivate::ErrorType::InvalidMax));
107 qCWarning(C_VALIDATOR).noquote()
108 << debugString(c) << "Invalid maximum comparison value:" << d->max;
109 } else {
110 if ((val < min) || (val > max)) {
111 result.errorMessage =
113 QVariantMap{{QStringLiteral("val"), val},
114 {QStringLiteral("min"), min},
115 {QStringLiteral("max"), max}});
116 qCDebug(C_VALIDATOR).noquote()
117 << debugString(c) << val << "is not between" << min << "and" << max;
118 } else {
119 valid = true;
120 }
121 }
122 }
123 }
124 } break;
125 case QMetaType::Float:
127 {
128 const double val = v.toDouble(&ok);
129 if (Q_UNLIKELY(!ok)) {
130 result.errorMessage = parsingError(c);
131 qCWarning(C_VALIDATOR).noquote().nospace()
132 << debugString(c) << " Can not parse input \"" << v
133 << "\" into a floating point number";
134 } else {
135 const double min = ValidatorBetweenPrivate::extractDouble(c, params, d->min, &ok);
136 if (Q_UNLIKELY(!ok)) {
138 c, static_cast<int>(ValidatorRulePrivate::ErrorType::InvalidMin));
139 qCWarning(C_VALIDATOR).noquote()
140 << debugString(c) << "Invalid mininum comparison value:" << d->min;
141 } else {
142 const double max =
143 ValidatorBetweenPrivate::extractDouble(c, params, d->max, &ok);
144 if (Q_UNLIKELY(!ok)) {
146 c, static_cast<int>(ValidatorRulePrivate::ErrorType::InvalidMax));
147 qCWarning(C_VALIDATOR).noquote()
148 << debugString(c) << "Invalid maximum comparison value:" << d->max;
149 } else {
150 if ((val < min) || (val > max)) {
151 result.errorMessage =
153 QVariantMap{{QStringLiteral("val"), val},
154 {QStringLiteral("min"), min},
155 {QStringLiteral("max"), max}});
156 qCDebug(C_VALIDATOR).noquote()
157 << debugString(c) << val << "is not between" << min << "and" << max;
158 } else {
159 valid = true;
160 }
161 }
162 }
163 }
164 } break;
166 {
167 const auto val = static_cast<qlonglong>(v.length());
168 const qlonglong min = ValidatorBetweenPrivate::extractLongLong(c, params, d->min, &ok);
169 if (Q_UNLIKELY(!ok)) {
171 c, static_cast<int>(ValidatorRulePrivate::ErrorType::InvalidMin));
172 qCWarning(C_VALIDATOR).noquote()
173 << debugString(c) << "Invalid mininum comparison value:" << d->min;
174 } else {
175 const qlonglong max =
176 ValidatorBetweenPrivate::extractLongLong(c, params, d->max, &ok);
177 if (Q_UNLIKELY(!ok)) {
179 c, static_cast<int>(ValidatorRulePrivate::ErrorType::InvalidMax));
180 qCWarning(C_VALIDATOR).noquote()
181 << debugString(c) << "Invalid maximum comparison value:" << d->max;
182 } else {
183 if ((val < min) || (val > max)) {
184 result.errorMessage =
186 QVariantMap{{QStringLiteral("val"), val},
187 {QStringLiteral("min"), min},
188 {QStringLiteral("max"), max}});
189 qCDebug(C_VALIDATOR).noquote() << debugString(c) << "String length" << val
190 << "is not between" << min << "and" << max;
191 } else {
192 valid = true;
193 }
194 }
195 }
196 } break;
197 default:
198 qCWarning(C_VALIDATOR).noquote()
199 << debugString(c) << "The comparison type" << d->type << "is not supported";
201 c, static_cast<int>(ValidatorRulePrivate::ErrorType::InvalidType));
202 break;
203 }
204
205 if (valid) {
206 if (d->type != QMetaType::QString) {
207 const QVariant _v = ValidatorBetweenPrivate::valueToNumber(c, v, d->type);
208 if (_v.isValid()) {
209 result.value = _v;
210 } else {
211 result.errorMessage = parsingError(c);
212 }
213 } else {
214 result.value.setValue(v);
215 }
216 }
217 } else {
218 defaultValue(c, &result);
219 }
220
221 return result;
222}
223
225{
226 cb(validate(c, params));
227}
228
230 const QVariant &errorData) const
231{
232 Q_D(const ValidatorBetween);
233
234 const QVariantMap map = errorData.toMap();
235 QString min;
236 QString max;
237 switch (d->type) {
238 case QMetaType::Char:
239 case QMetaType::Short:
240 case QMetaType::Int:
241 case QMetaType::Long:
244 min = c->locale().toString(map.value(QStringLiteral("min")).toLongLong());
245 max = c->locale().toString(map.value(QStringLiteral("max")).toLongLong());
246 break;
247 case QMetaType::UChar:
249 case QMetaType::UInt:
250 case QMetaType::ULong:
252 min = c->locale().toString(map.value(QStringLiteral("min")).toULongLong());
253 max = c->locale().toString(map.value(QStringLiteral("max")).toULongLong());
254 break;
255 case QMetaType::Float:
257 min = c->locale().toString(map.value(QStringLiteral("min")).toDouble());
258 max = c->locale().toString(map.value(QStringLiteral("max")).toDouble());
259 break;
260 default:
261 return validationDataError(c);
262 }
263
264 const QString _label = label(c);
265
266 if (_label.isEmpty()) {
267 if (d->type == QMetaType::QString) {
268 //: %1 will be replaced by the minimum, %2 by the maximum value
269 //% "The text must be between %1 and %2 characters long."
270 return c->qtTrId("cutelyst-valbetween-genvalerr-string").arg(min, max);
271 } else {
272 //: %1 will be replaced by the minimum, %2 by the maximum value
273 //% "The value must be between %1 and %2."
274 return c->qtTrId("cutelyst-valbetween-genvalerr-num").arg(min, max);
275 }
276 } else {
277 if (d->type == QMetaType::QString) {
278 //: %1 will be replaced by the field label, %2 by the minimum and %3 by the
279 //: maximum value
280 //% "The text in the “%1“ field must be between %2 and %3 characters long."
281 return c->qtTrId("cutelyst-valbetween-genvalerr-string-label").arg(_label, min, max);
282 } else {
283 //: %1 will be replaced by the field label, %2 by the minimum and %3 by the
284 //: maximum value
285 //% "The value in the “%1” field must be between %2 and %3."
286 return c->qtTrId("cutelyst-valbetween-genvalerr-num-label").arg(_label, min, max);
287 }
288 }
289
290 return {};
291}
292
294{
295 const auto errorType = static_cast<ValidatorRulePrivate::ErrorType>(errorData.toInt());
296 const QString _label = label(c);
297
298 if (_label.isEmpty()) {
299 switch (errorType) {
300 case ValidatorRulePrivate::ErrorType::InvalidMin:
301 //% "The minimum comparison value is not valid."
302 return c->qtTrId("cutelyst-validator-genvaldataerr-min");
303 case ValidatorRulePrivate::ErrorType::InvalidType:
304 {
305 Q_D(const ValidatorBetween);
306 QMetaType _type(d->type);
307 //: %1 will be replaced by the name of the comparison type
308 //% "The comparison type %1 is not supported."
309 return c->qtTrId("cutelyst-validator-genvaldataerr-type")
310 .arg(QString::fromLatin1(_type.name()));
311 }
312 case ValidatorRulePrivate::ErrorType::InvalidMax:
313 //% "The maximum comparison value is not valid."
314 return c->qtTrId("cutelyst-validator-genvaldataerr-max");
315 }
316 } else {
317 switch (errorType) {
318 case ValidatorRulePrivate::ErrorType::InvalidMin:
319 //: %1 will be replaced by the field label
320 //% "The minimum comparison value for the “%1” field is not valid."
321 return c->qtTrId("cutelyst-validator-genvaldataerr-min-label").arg(_label);
322 case ValidatorRulePrivate::ErrorType::InvalidType:
323 {
324 Q_D(const ValidatorBetween);
325 QMetaType _type(d->type);
326 //: %1 will be replaced by the type name, %2 will be replaced by the field label
327 //% "The comparison type %1 for the “%2” field is not supported."
328 return c->qtTrId("cutelyst-validator-genvaldataerr-type-label")
329 .arg(QString::fromLatin1(_type.name()), _label);
330 }
331 case ValidatorRulePrivate::ErrorType::InvalidMax:
332 //: %1 will be replaced by the field label
333 //% "The maximum comparison value for the “%1” field is not valid."
334 return c->qtTrId("cutelyst-validator-genvaldataerr-max-label").arg(_label);
335 }
336 }
337
338 return {};
339}
340
342{
343 Q_UNUSED(errorData)
344 Q_D(const ValidatorBetween);
345
346 const QString _label = label(c);
347 if ((d->type == QMetaType::Float) || (d->type == QMetaType::Double)) {
348 if (_label.isEmpty()) {
349 //% "Failed to parse the input value into a floating point number."
350 return c->qtTrId("cutelyst-validator-genparseerr-float");
351 } else {
352 //: %1 will be replaced by the field label
353 //% "Failed to parse the input value for the “%1” field into a "
354 //% "floating point number."
355 return c->qtTrId("cutelyst-validator-genparseerr-float-label").arg(_label);
356 }
357 } else {
358 if (_label.isEmpty()) {
359 //% "Failed to parse the input value into an integer number."
360 return c->qtTrId("cutelyst-validator-genparseerr-int");
361 } else {
362 //: %1 will be replaced by the field label
363 //% "Failed to parse the input value for the “%1” field into an integer number."
364 return c->qtTrId("cutelyst-validator-genparseerr-int-label").arg(_label);
365 }
366 }
367}
The Cutelyst Context.
Definition context.h:42
QLocale locale() const noexcept
Definition context.cpp:461
QString qtTrId(const char *id, int n=-1) const
Definition context.h:657
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={})
void validateCb(Context *c, const ParamsMultiMap &params, ValidatorRtFn cb) const override
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(const Context *c) const
QString debugString(const Context *c) const
QString validationDataError(Context *c, const QVariant &errorData={}) const
std::function< void(ValidatorReturnType &&result)> ValidatorRtFn
Void callback function for validator rules that processes the ValidatorReturnType.
void defaultValue(Context *c, ValidatorReturnType *result) const
QString value(const ParamsMultiMap &params) const
QString parsingError(Context *c, const QVariant &errorData={}) 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.