cutelyst 3.9.1
A C++ Web Framework built on top of Qt, using the simple approach of Catalyst (Perl) framework.
validatorfilesize.cpp
1/*
2 * SPDX-FileCopyrightText: (C) 2018-2022 Matthias Fehring <mf@huessenbergnetz.de>
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5
6#include "validatorfilesize_p.h"
7
8#include <cmath>
9#include <limits>
10
11using namespace Cutelyst;
12
14 Option option,
15 const QVariant &min,
16 const QVariant &max,
17 const ValidatorMessages &messages,
18 const QString &defValKey)
19 : ValidatorRule(*new ValidatorFileSizePrivate(field, option, min, max, messages, defValKey))
20{
21}
22
26
28 double min,
29 double max,
31 const QLocale &locale,
32 double *fileSize)
33{
34 bool valid = true;
35
36 QString digitPart;
37 QString symbolPart;
38 bool decimalPointFound = false;
39 const QString decimalPoint(locale.decimalPoint());
40 int multiplier = 0;
41 bool binary = false;
42 bool byteSignFound = false;
43 qint8 startsWith = 0; // 0 not set, -1 digit part, 1 symbol part
44
45 for (const QChar &ch : value) {
46 if (valid) {
47 const ushort &uc = ch.unicode();
48 if (((uc > 47) && (uc < 58)) || (ch == decimalPoint)) {
49 if (startsWith == 0) {
50 startsWith = -1;
51 }
52 if (ch == decimalPoint) {
53 if (decimalPointFound) {
54 valid = false;
55 break;
56 } else {
57 decimalPointFound = true;
58 }
59 }
60 if ((symbolPart.isEmpty() && (startsWith < 0)) ||
61 (!symbolPart.isEmpty() && (startsWith > 0))) {
62 digitPart.append(ch);
63 } else {
64 valid = false;
65 break;
66 }
67 } else if ((uc != 9) &&
68 (uc != 32)) { // not a digit or decimal point and not a space or tab
69 if (startsWith == 0) {
70 startsWith = 1;
71 }
72 if ((digitPart.isEmpty() && (startsWith > 0)) ||
73 (!digitPart.isEmpty() && (startsWith < 0))) {
74 switch (uc) {
75 case 75: // K
76 case 107: // k
77 {
78 if (multiplier > 0) {
79 valid = false;
80 } else {
81 multiplier = 1;
82 symbolPart.append(ch);
83 }
84 } break;
85 case 77: // M
86 case 109: // m
87 {
88 if (multiplier > 0) {
89 valid = false;
90 } else {
91 multiplier = 2;
92 symbolPart.append(ch);
93 }
94 } break;
95 case 71: // G
96 case 103: // g
97 {
98 if (multiplier > 0) {
99 valid = false;
100 } else {
101 multiplier = 3;
102 symbolPart.append(ch);
103 }
104 } break;
105 case 84: // T
106 case 116: // t
107 {
108 if (multiplier > 0) {
109 valid = false;
110 } else {
111 multiplier = 4;
112 symbolPart.append(ch);
113 }
114 } break;
115 case 80: // P
116 case 112: // p
117 {
118 if (multiplier > 0) {
119 valid = false;
120 } else {
121 multiplier = 5;
122 symbolPart.append(ch);
123 }
124 } break;
125 case 69: // E
126 case 101: // e
127 {
128 if (multiplier > 0) {
129 valid = false;
130 } else {
131 multiplier = 6;
132 symbolPart.append(ch);
133 }
134 } break;
135 case 90: // Z
136 case 122: // z
137 {
138 if (multiplier > 0) {
139 valid = false;
140 } else {
141 multiplier = 7;
142 symbolPart.append(ch);
143 }
144 } break;
145 case 89: // Y
146 case 121: // y
147 {
148 if (multiplier > 0) {
149 valid = false;
150 } else {
151 multiplier = 8;
152 symbolPart.append(ch);
153 }
154 } break;
155 case 73: // I
156 case 105: // i
157 {
158 if ((multiplier == 0) || binary) {
159 valid = false;
160 } else {
161 binary = true;
162 symbolPart.append(ch);
163 }
164 } break;
165 case 66: // B
166 case 98: // b
167 {
168 if (byteSignFound) {
169 valid = false;
170 } else {
171 byteSignFound = true;
172 symbolPart.append(ch);
173 }
174 } break;
175 case 9: // horizontal tab
176 case 32: // space
177 break;
178 default:
179 valid = false;
180 break;
181 }
182 } else {
183 valid = false;
184 break;
185 }
186 }
187 } else {
188 break;
189 }
190 }
191
192 if ((option == OnlyBinary) && !binary) {
193 valid = false;
194 } else if ((option == OnlyDecimal) && binary) {
195 valid = false;
196 } else if (option == ForceBinary) {
197 binary = true;
198 } else if (option == ForceDecimal) {
199 binary = false;
200 }
201
202 if (valid) {
203 bool ok = false;
204 double size = locale.toDouble(digitPart, &ok);
205 if (!ok) {
206 valid = false;
207 } else {
208 if (multiplier > 0) {
209 const double _mult =
210 binary ? std::exp2(multiplier * 10) : std::pow(10.0, multiplier * 3);
211 size *= _mult;
212 }
213 if ((min >= 1.0) && (size < min)) {
214 valid = false;
215 }
216 if ((max >= 1.0) && (size > max)) {
217 valid = false;
218 }
219 if (valid && fileSize) {
220 *fileSize = size;
221 }
222 }
223 }
224
225 return valid;
226}
227
229{
230 ValidatorReturnType result;
231
232 Q_D(const ValidatorFileSize);
233
234 const QString v = value(params);
235
236 if (!v.isEmpty()) {
237
238 double min = -1;
239 double max = -1;
240 bool ok = true;
241 if (d->min.isValid()) {
242 min = d->extractDouble(c, params, d->min, &ok);
243 if (!ok) {
244 result.errorMessage = validationDataError(c, 0);
245 }
246 }
247
248 if (ok && d->max.isValid()) {
249 max = d->extractDouble(c, params, d->max, &ok);
250 if (!ok) {
251 result.errorMessage = validationDataError(c, 1);
252 }
253 }
254
255 if (ok) {
256 double size = 0;
257 if (ValidatorFileSize::validate(v, min, max, d->option, c->locale(), &size)) {
258 if (size < static_cast<double>(std::numeric_limits<qulonglong>::max())) {
259 result.value.setValue<qulonglong>(static_cast<qulonglong>(size + 0.5));
260 } else {
261 result.value.setValue(size);
262 }
263 } else {
264 result.errorMessage = validationError(c);
265 }
266 }
267
268 } else {
269 defaultValue(c, &result, "ValidatorFileSize");
270 }
271
272 return result;
273}
274
276{
277 QString error;
278 Q_D(const ValidatorFileSize);
279 Q_UNUSED(errorData)
280 const QString _label = label(c);
281 if (d->min.isValid() || d->max.isValid()) {
282 if (_label.isEmpty()) {
283 error = c->translate("Cutelyst::ValidatorFileSize",
284 "Invalid file size or file size not within the allowed limits.");
285 } else {
286 error = c->translate("Cutelyst::ValidatorFileSize",
287 "The value in the “%1” field is either not a valid file size or "
288 "not within the allowed limits.")
289 .arg(_label);
290 }
291 } else {
292 if (_label.isEmpty()) {
293 error = c->translate("Cutelyst::ValidatorFileSize", "Invalid file size.");
294 } else {
295 error = c->translate("Cutelyst::ValidatorFileSize",
296 "The “%1” field does not contain a valid file size.")
297 .arg(_label);
298 }
299 }
300
301 return error;
302}
303
305{
306 QString error;
307
308 const QString _label = label(c);
309
310 const int sizeType = errorData.toInt();
311
312 if (sizeType == 0) { // minimum file size
313 if (_label.isEmpty()) {
314 error = c->translate("Cutelyst::ValidatorFileSize",
315 "The minimum file size comparison value is not valid.");
316 } else {
317 error = c->translate(
318 "Cutelyst::ValidatorFileSize",
319 "The minimum file size comparison value for the “%1” field is not valid.")
320 .arg(_label);
321 }
322 } else {
323 if (_label.isEmpty()) {
324 error = c->translate("Cutelyst::ValidatorFileSize",
325 "The maximum file size comparison value is not valid.");
326 } else {
327 error = c->translate(
328 "Cutelyst::ValidatorFileSize",
329 "The maximum file size comparison value for the “%1” field is not valid.")
330 .arg(_label);
331 }
332 }
333
334 return error;
335}
336
338{
339 Q_ASSERT(c);
340 c->setStash(stashKey,
342 ? QStringLiteral("^\\d+[,.٫]?\\d*\\s*[KkMmGgTt]?[Ii]?[Bb]?")
343 : QStringLiteral("[KkMmGgTt]?[Ii]?[Bb]?\\s*\\d+[,.٫]?\\d*"));
344}
The Cutelyst Context.
Definition context.h:39
QLocale locale() const noexcept
Definition context.cpp:466
QString translate(const char *context, const char *sourceText, const char *disambiguation=nullptr, int n=-1) const
Definition context.cpp:490
void setStash(const QString &key, const QVariant &value)
Definition context.cpp:217
~ValidatorFileSize() override
Deconstructs the file size validator.
QString genericValidationDataError(Context *c, const QVariant &errorData) const override
Returns a generic error messages if validation data is missing or invalid.
Option
Options for ValidatorFileSize.
QString genericValidationError(Context *c, const QVariant &errorData=QVariant()) const override
Returns a generic error message if validation failed.
static void inputPattern(Context *c, const QString &stashKey=QStringLiteral("fileSizePattern"))
Puts an HTML input pattern for file sizes into the stash.
ValidatorFileSize(const QString &field, Option option=NoOption, const QVariant &min=QVariant(), const QVariant &max=QVariant(), const ValidatorMessages &messages=ValidatorMessages(), const QString &defValKey=QString())
Constructs a new file size validator.
QString label(Context *c) const
Returns the human readable field label used for generic error messages.
QString field() const
Returns the name of the field to validate.
void defaultValue(Context *c, ValidatorReturnType *result, const char *validatorName) const
I a defValKey has been set in the constructor, this will try to get the default value from the stash ...
ValidatorRule(const QString &field, const ValidatorMessages &messages=ValidatorMessages(), const QString &defValKey=QString())
Constructs a new ValidatorRule with the given parameters.
QString value(const ParamsMultiMap &params) const
Returns the value of the field from the input params.
QString validationDataError(Context *c, const QVariant &errorData=QVariant()) const
Returns an error message if any validation data is missing or invalid.
QString validationError(Context *c, const QVariant &errorData=QVariant()) const
Returns a descriptive error message if validation failed.
static bool validate(const QString &value, double min=-1, double max=-1, Option option=NoOption, const QLocale &locale=QLocale(), double *fileSize=nullptr)
Returns true if value is a valid file size string.
The Cutelyst namespace holds all public Cutelyst API.
Definition Mainpage.dox:8
QMultiMap< QString, QString > ParamsMultiMap
QChar decimalPoint() const const
Qt::LayoutDirection textDirection() const const
double toDouble(const QString &s, bool *ok) const const
QString & append(QChar ch)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
bool isEmpty() const const
LeftToRight
void setValue(const T &value)
int toInt(bool *ok) const const
Stores custom error messages and the input field label.
Contains the result of a single input parameter validation.