cutelyst  4.4.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 
10 using 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 {
26  ValidatorReturnType result;
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:
38  case QMetaType::Short:
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;
79  case QMetaType::UChar:
80  case QMetaType::UShort:
81  case QMetaType::UInt:
82  case QMetaType::ULong:
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 =
108  validationError(c,
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:
122  case QMetaType::Double:
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 =
147  validationError(c,
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;
160  case QMetaType::QString:
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 =
179  validationError(c,
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:
232  case QMetaType::LongLong:
233  case QMetaType::QString:
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:
238  case QMetaType::UShort:
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:
246  case QMetaType::Double:
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.
Definition: validatorrule.h:49