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;
11using namespace Qt::StringLiterals;
12
14 QMetaType::Type type,
15 const QVariant &min,
16 const QVariant &max,
17 const ValidatorMessages &messages,
18 const QString &defValKey)
19 : ValidatorRule(*new ValidatorBetweenPrivate(field, type, min, max, messages, defValKey))
20{
21}
22
24
26{
28
29 const QString v = value(params);
30
31 Q_D(const ValidatorBetween);
32
33 if (!v.isEmpty()) {
34 bool ok = false;
35 bool valid = false;
36
37 switch (d->type) {
38 case QMetaType::Char:
40 case QMetaType::Int:
41 case QMetaType::Long:
43 {
44 const qlonglong val = c->locale().toLongLong(v, &ok);
45 if (Q_UNLIKELY(!ok)) {
46 result.errorMessage = parsingError(c);
47 qCWarning(C_VALIDATOR).noquote().nospace()
48 << debugString(c) << " Can not parse input \"" << v
49 << "\" into an integer number";
50 } else {
51 const qlonglong min =
52 ValidatorBetweenPrivate::extractLongLong(c, params, d->min, &ok);
53 if (Q_UNLIKELY(!ok)) {
55 c, static_cast<int>(ValidatorRulePrivate::ErrorType::InvalidMin));
56 qCWarning(C_VALIDATOR).noquote()
57 << "Invalid mininum comparison value:" << d->min;
58 } else {
59 const qlonglong max =
60 ValidatorBetweenPrivate::extractLongLong(c, params, d->max, &ok);
61 if (Q_UNLIKELY(!ok)) {
63 c, static_cast<int>(ValidatorRulePrivate::ErrorType::InvalidMax));
64 qCWarning(C_VALIDATOR).noquote()
65 << "Invalid maximum comparison value:" << d->max;
66 } else {
67 if ((val < min) || (val > max)) {
69 c, QVariantMap{{u"val"_s, val}, {u"min"_s, min}, {u"max"_s, 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 =
93 ValidatorBetweenPrivate::extractULongLong(c, params, d->min, &ok);
94 if (Q_UNLIKELY(!ok)) {
96 c, static_cast<int>(ValidatorRulePrivate::ErrorType::InvalidMin));
97 qCWarning(C_VALIDATOR).noquote()
98 << debugString(c) << "Invalid mininum comparison value:" << d->min;
99 } else {
100 const qulonglong max =
101 ValidatorBetweenPrivate::extractULongLong(c, params, d->max, &ok);
102 if (Q_UNLIKELY(!ok)) {
104 c, static_cast<int>(ValidatorRulePrivate::ErrorType::InvalidMax));
105 qCWarning(C_VALIDATOR).noquote()
106 << debugString(c) << "Invalid maximum comparison value:" << d->max;
107 } else {
108 if ((val < min) || (val > max)) {
110 c, QVariantMap{{u"val"_s, val}, {u"min"_s, min}, {u"max"_s, max}});
111 qCDebug(C_VALIDATOR).noquote()
112 << debugString(c) << val << "is not between" << min << "and" << max;
113 } else {
114 valid = true;
115 }
116 }
117 }
118 }
119 } break;
120 case QMetaType::Float:
122 {
123 const double val = v.toDouble(&ok);
124 if (Q_UNLIKELY(!ok)) {
125 result.errorMessage = parsingError(c);
126 qCWarning(C_VALIDATOR).noquote().nospace()
127 << debugString(c) << " Can not parse input \"" << v
128 << "\" into a floating point number";
129 } else {
130 const double min = ValidatorBetweenPrivate::extractDouble(c, params, d->min, &ok);
131 if (Q_UNLIKELY(!ok)) {
133 c, static_cast<int>(ValidatorRulePrivate::ErrorType::InvalidMin));
134 qCWarning(C_VALIDATOR).noquote()
135 << debugString(c) << "Invalid mininum comparison value:" << d->min;
136 } else {
137 const double max =
138 ValidatorBetweenPrivate::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)) {
147 c, QVariantMap{{u"val"_s, val}, {u"min"_s, min}, {u"max"_s, max}});
148 qCDebug(C_VALIDATOR).noquote()
149 << debugString(c) << val << "is not between" << min << "and" << max;
150 } else {
151 valid = true;
152 }
153 }
154 }
155 }
156 } break;
158 {
159 const auto val = static_cast<qlonglong>(v.length());
160 const qlonglong min = ValidatorBetweenPrivate::extractLongLong(c, params, d->min, &ok);
161 if (Q_UNLIKELY(!ok)) {
163 c, static_cast<int>(ValidatorRulePrivate::ErrorType::InvalidMin));
164 qCWarning(C_VALIDATOR).noquote()
165 << debugString(c) << "Invalid mininum comparison value:" << d->min;
166 } else {
167 const qlonglong max =
168 ValidatorBetweenPrivate::extractLongLong(c, params, d->max, &ok);
169 if (Q_UNLIKELY(!ok)) {
171 c, static_cast<int>(ValidatorRulePrivate::ErrorType::InvalidMax));
172 qCWarning(C_VALIDATOR).noquote()
173 << debugString(c) << "Invalid maximum comparison value:" << d->max;
174 } else {
175 if ((val < min) || (val > max)) {
177 c, QVariantMap{{u"val"_s, val}, {u"min"_s, min}, {u"max"_s, max}});
178 qCDebug(C_VALIDATOR).noquote() << debugString(c) << "String length" << val
179 << "is not between" << min << "and" << max;
180 } else {
181 valid = true;
182 }
183 }
184 }
185 } break;
186 default:
187 qCWarning(C_VALIDATOR).noquote()
188 << debugString(c) << "The comparison type" << d->type << "is not supported";
190 c, static_cast<int>(ValidatorRulePrivate::ErrorType::InvalidType));
191 break;
192 }
193
194 if (valid) {
195 if (d->type != QMetaType::QString) {
196 const QVariant _v = ValidatorBetweenPrivate::valueToNumber(c, v, d->type);
197 if (_v.isValid()) {
198 result.value = _v;
199 } else {
200 result.errorMessage = parsingError(c);
201 }
202 } else {
203 result.value.setValue(v);
204 }
205 }
206 } else {
207 defaultValue(c, &result);
208 }
209
210 return result;
211}
212
214{
215 cb(validate(c, params));
216}
217
219 const QVariant &errorData) const
220{
221 Q_D(const ValidatorBetween);
222
223 const QVariantMap map = errorData.toMap();
224 QString min;
225 QString max;
226 switch (d->type) {
227 case QMetaType::Char:
228 case QMetaType::Short:
229 case QMetaType::Int:
230 case QMetaType::Long:
233 min = c->locale().toString(map.value(u"min"_s).toLongLong());
234 max = c->locale().toString(map.value(u"max"_s).toLongLong());
235 break;
236 case QMetaType::UChar:
238 case QMetaType::UInt:
239 case QMetaType::ULong:
241 min = c->locale().toString(map.value(u"min"_s).toULongLong());
242 max = c->locale().toString(map.value(u"max"_s).toULongLong());
243 break;
244 case QMetaType::Float:
246 min = c->locale().toString(map.value(u"min"_s).toDouble());
247 max = c->locale().toString(map.value(u"max"_s).toDouble());
248 break;
249 default:
250 return validationDataError(c);
251 }
252
253 const QString _label = label(c);
254
255 if (_label.isEmpty()) {
256 if (d->type == QMetaType::QString) {
257 //: %1 will be replaced by the minimum, %2 by the maximum value
258 //% "The text must be between %1 and %2 characters long."
259 return c->qtTrId("cutelyst-valbetween-genvalerr-string").arg(min, max);
260 } else {
261 //: %1 will be replaced by the minimum, %2 by the maximum value
262 //% "The value must be between %1 and %2."
263 return c->qtTrId("cutelyst-valbetween-genvalerr-num").arg(min, max);
264 }
265 } else {
266 if (d->type == QMetaType::QString) {
267 //: %1 will be replaced by the field label, %2 by the minimum and %3 by the
268 //: maximum value
269 //% "The text in the “%1“ field must be between %2 and %3 characters long."
270 return c->qtTrId("cutelyst-valbetween-genvalerr-string-label").arg(_label, min, max);
271 } else {
272 //: %1 will be replaced by the field label, %2 by the minimum and %3 by the
273 //: maximum value
274 //% "The value in the “%1” field must be between %2 and %3."
275 return c->qtTrId("cutelyst-valbetween-genvalerr-num-label").arg(_label, min, max);
276 }
277 }
278
279 return {};
280}
281
283{
284 const auto errorType = static_cast<ValidatorRulePrivate::ErrorType>(errorData.toInt());
285 const QString _label = label(c);
286
287 if (_label.isEmpty()) {
288 switch (errorType) {
289 case ValidatorRulePrivate::ErrorType::InvalidMin:
290 //% "The minimum comparison value is not valid."
291 return c->qtTrId("cutelyst-validator-genvaldataerr-min");
292 case ValidatorRulePrivate::ErrorType::InvalidType:
293 {
294 Q_D(const ValidatorBetween);
295 QMetaType _type(d->type);
296 //: %1 will be replaced by the name of the comparison type
297 //% "The comparison type %1 is not supported."
298 return c->qtTrId("cutelyst-validator-genvaldataerr-type")
299 .arg(QString::fromLatin1(_type.name()));
300 }
301 case ValidatorRulePrivate::ErrorType::InvalidMax:
302 //% "The maximum comparison value is not valid."
303 return c->qtTrId("cutelyst-validator-genvaldataerr-max");
304 }
305 } else {
306 switch (errorType) {
307 case ValidatorRulePrivate::ErrorType::InvalidMin:
308 //: %1 will be replaced by the field label
309 //% "The minimum comparison value for the “%1” field is not valid."
310 return c->qtTrId("cutelyst-validator-genvaldataerr-min-label").arg(_label);
311 case ValidatorRulePrivate::ErrorType::InvalidType:
312 {
313 Q_D(const ValidatorBetween);
314 QMetaType _type(d->type);
315 //: %1 will be replaced by the type name, %2 will be replaced by the field label
316 //% "The comparison type %1 for the “%2” field is not supported."
317 return c->qtTrId("cutelyst-validator-genvaldataerr-type-label")
318 .arg(QString::fromLatin1(_type.name()), _label);
319 }
320 case ValidatorRulePrivate::ErrorType::InvalidMax:
321 //: %1 will be replaced by the field label
322 //% "The maximum comparison value for the “%1” field is not valid."
323 return c->qtTrId("cutelyst-validator-genvaldataerr-max-label").arg(_label);
324 }
325 }
326
327 return {};
328}
329
331{
332 Q_UNUSED(errorData)
333 Q_D(const ValidatorBetween);
334
335 const QString _label = label(c);
336 if ((d->type == QMetaType::Float) || (d->type == QMetaType::Double)) {
337 if (_label.isEmpty()) {
338 //% "Failed to parse the input value into a floating point number."
339 return c->qtTrId("cutelyst-validator-genparseerr-float");
340 } else {
341 //: %1 will be replaced by the field label
342 //% "Failed to parse the input value for the “%1” field into a "
343 //% "floating point number."
344 return c->qtTrId("cutelyst-validator-genparseerr-float-label").arg(_label);
345 }
346 } else {
347 if (_label.isEmpty()) {
348 //% "Failed to parse the input value into an integer number."
349 return c->qtTrId("cutelyst-validator-genparseerr-int");
350 } else {
351 //: %1 will be replaced by the field label
352 //% "Failed to parse the input value for the “%1” field into an integer number."
353 return c->qtTrId("cutelyst-validator-genparseerr-int-label").arg(_label);
354 }
355 }
356}
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.