1 /* 2 * Copyright (C) 2017-2018 Matthias Fehring <kontakt@buschmann23.de> 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 #ifndef CUTELYSTVALIDATORRULE_P_H 19 #define CUTELYSTVALIDATORRULE_P_H 20 21 #include "validatorrule.h" 22 #include <QDate> 23 #include <QTime> 24 #include <QDateTime> 25 #include <QTimeZone> 26 #include <QLocale> 27 #include <Cutelyst/Context> 28 #include <limits> 29 30 namespace Cutelyst { 31 32 class ValidatorRulePrivate 33 { Q_DISABLE_COPY(ValidatorRulePrivate)34 Q_DISABLE_COPY(ValidatorRulePrivate) 35 public: 36 ValidatorRulePrivate() {} 37 ValidatorRulePrivate(const QString & f,const ValidatorMessages & m,const QString & dvk)38 ValidatorRulePrivate(const QString &f, const ValidatorMessages &m, const QString &dvk) : 39 field(f), 40 defValKey(dvk), 41 messages(m) 42 {} 43 ~ValidatorRulePrivate()44 virtual ~ValidatorRulePrivate() {} 45 46 QDate extractDate(Context *c, const QString &date, const char *format = nullptr) const 47 { 48 QDate d; 49 50 Q_ASSERT(c); 51 52 if (format) { 53 const QString _format = translationContext.size() ? c->translate(translationContext.data(), format) : QString::fromUtf8(format); 54 d = QDate::fromString(date, _format); 55 if (d.isValid()) { 56 return d; 57 } 58 d = c->locale().toDate(date, _format); 59 if (d.isValid()) { 60 return d; 61 } 62 } 63 64 for (QLocale::FormatType f : {QLocale::ShortFormat, QLocale::LongFormat}) { 65 d = c->locale().toDate(date, f); 66 if (d.isValid()) { 67 return d; 68 } 69 } 70 71 for (Qt::DateFormat f : {Qt::ISODate, Qt::RFC2822Date, Qt::TextDate}) { 72 d = QDate::fromString(date, f); 73 if (d.isValid()) { 74 return d; 75 } 76 } 77 78 return d; 79 } 80 81 82 QTime extractTime(Context *c, const QString &time, const char *format = nullptr) const 83 { 84 QTime t; 85 86 Q_ASSERT(c); 87 88 if (format) { 89 const QString _format = translationContext.size() ? c->translate(translationContext.data(), format) : QString::fromUtf8(format); 90 t = QTime::fromString(time, _format); 91 if (t.isValid()) { 92 return t; 93 } 94 t = c->locale().toTime(time, _format); 95 if (t.isValid()) { 96 return t; 97 } 98 } 99 100 for (QLocale::FormatType f : {QLocale::ShortFormat, QLocale::LongFormat}) { 101 t = c->locale().toTime(time, f); 102 if (t.isValid()) { 103 return t; 104 } 105 } 106 107 for (Qt::DateFormat f : {Qt::ISODate, Qt::RFC2822Date, Qt::TextDate}) { 108 t = QTime::fromString(time, f); 109 if (t.isValid()) { 110 return t; 111 } 112 } 113 114 return t; 115 } 116 117 118 QDateTime extractDateTime(Context *c, const QString &dateTime, const char *format = nullptr, const QTimeZone &tz = QTimeZone()) const 119 { 120 QDateTime dt; 121 122 Q_ASSERT(c); 123 124 if (format) { 125 const QString _format = translationContext.size() ? c->translate(translationContext.data(), format) : QString::fromUtf8(format); 126 dt = QDateTime::fromString(dateTime, _format); 127 if (dt.isValid()) { 128 if (tz.isValid()) { 129 dt.setTimeZone(tz); 130 } 131 return dt; 132 } 133 134 dt = c->locale().toDateTime(dateTime, _format); 135 if (dt.isValid()) { 136 if (tz.isValid()) { 137 dt.setTimeZone(tz); 138 } 139 return dt; 140 } 141 } 142 143 for (QLocale::FormatType f : {QLocale::ShortFormat, QLocale::LongFormat}) { 144 dt = c->locale().toDateTime(dateTime, f); 145 if (dt.isValid()) { 146 if (tz.isValid()) { 147 dt.setTimeZone(tz); 148 } 149 return dt; 150 } 151 } 152 153 for (Qt::DateFormat f : {Qt::ISODate, Qt::RFC2822Date, Qt::TextDate}) { 154 dt = QDateTime::fromString(dateTime, f); 155 if (dt.isValid()) { 156 if (tz.isValid()) { 157 dt.setTimeZone(tz); 158 } 159 return dt; 160 } 161 } 162 163 return dt; 164 } 165 166 QVariant extractOtherDateTime(Context *c, const ParamsMultiMap ¶ms, const QString &field, const QTimeZone &tz = QTimeZone(), const char *format = nullptr) const 167 { 168 QVariant var; 169 170 Q_ASSERT(c); 171 172 int sepPos = field.indexOf(QLatin1Char('|')); 173 if (sepPos > -1) { 174 const QString fieldName = field.left(sepPos); 175 const QString value = params.value(fieldName); 176 if (!value.isEmpty()) { 177 const QString type = field.mid(sepPos + 1); 178 if (type.startsWith(QLatin1String("dt"))) { 179 QDateTime dt = extractDateTime(c, value, format); 180 if (dt.isValid()) { 181 if (tz.isValid()) { 182 dt.setTimeZone(tz); 183 } 184 var = dt; 185 } 186 } else if (type.startsWith(QLatin1Char('t'))) { 187 const QTime t = extractTime(c, value, format); 188 if (t.isValid()) { 189 var = t; 190 } 191 } else if (type.startsWith(QLatin1Char('d'))) { 192 const QDate d = extractDate(c, value, format); 193 if (d.isValid()) { 194 var = d; 195 } 196 } 197 } 198 } else { 199 var = c->stash(field); 200 } 201 202 return var; 203 } 204 extractTimeZone(Context * c,const ParamsMultiMap & params,const QString & field)205 static QTimeZone extractTimeZone(Context *c, const ParamsMultiMap ¶ms, const QString &field) 206 { 207 QTimeZone tz; 208 209 Q_ASSERT(c); 210 Q_UNUSED(params) 211 212 tz = QTimeZone(field.toLatin1()); 213 214 if (!tz.isValid()) { 215 const QString tzString = params.value(field, c->stash(field).toString()); 216 // const QString tzString = c->stash(field).toString(); 217 if (!tzString.isEmpty()) { 218 tz = QTimeZone(tzString.toLatin1()); 219 if (!tz.isValid()) { 220 tz = QTimeZone(tzString.toInt()); 221 } 222 } 223 } 224 225 return tz; 226 } 227 extractLongLong(Context * c,const ParamsMultiMap & params,const QVariant & value,bool * ok)228 static qlonglong extractLongLong(Context *c, const ParamsMultiMap ¶ms, const QVariant &value, bool *ok) 229 { 230 qlonglong val = 0; 231 232 Q_ASSERT(c); 233 Q_ASSERT(ok); 234 Q_UNUSED(params) 235 236 if (value.userType() == QMetaType::QString) { 237 const QString field = value.toString(); 238 /* if (params.contains(field)) { 239 const QString v = params.value(field); 240 val = v.toLongLong(ok); 241 // if (!*ok) { 242 // val = c->locale().toLongLong(v, ok); 243 // } 244 } else */if (c->stash().contains(field)) { 245 val = c->stash(field).toLongLong(ok); 246 } else { 247 *ok = false; 248 } 249 } else { 250 val = value.toLongLong(ok); 251 } 252 253 return val; 254 } 255 extractULongLong(Context * c,const ParamsMultiMap & params,const QVariant & value,bool * ok)256 static qulonglong extractULongLong(Context *c, const ParamsMultiMap ¶ms, const QVariant &value, bool *ok) 257 { 258 qulonglong val = 0; 259 260 Q_ASSERT(c); 261 Q_ASSERT(ok); 262 Q_UNUSED(params) 263 264 if (value.userType() == QMetaType::QString) { 265 const QString field = value.toString(); 266 /* if (params.contains(field)) { 267 const QString v = params.value(field); 268 val = v.toULongLong(ok); 269 // if (!*ok) { 270 // val = c->locale().toULongLong(v, ok); 271 // } 272 } else */if (c->stash().contains(field)) { 273 val = c->stash(field).toULongLong(ok); 274 } else { 275 *ok = false; 276 } 277 } else { 278 val = value.toULongLong(ok); 279 } 280 281 return val; 282 } 283 extractDouble(Context * c,const ParamsMultiMap & params,const QVariant & value,bool * ok)284 static double extractDouble(Context *c, const ParamsMultiMap ¶ms, const QVariant &value, bool *ok) 285 { 286 double val = 0.0; 287 288 Q_ASSERT(c); 289 Q_ASSERT(ok); 290 Q_UNUSED(params) 291 292 if (value.userType() == QMetaType::QString) { 293 const QString field = value.toString(); 294 /* if (params.contains(field)) { 295 const QString v = params.value(field); 296 val = v.toDouble(ok); 297 // if (!*ok) { 298 // val = c->locale().toDouble(v, ok); 299 // } 300 } else*/ if (c->stash().contains(field)) { 301 val = c->stash(field).toDouble(ok); 302 } else { 303 *ok = false; 304 } 305 } else { 306 val = value.toDouble(ok); 307 } 308 309 return val; 310 } 311 extractInt(Context * c,const ParamsMultiMap & params,const QVariant & value,bool * ok)312 static int extractInt(Context *c, const ParamsMultiMap ¶ms, const QVariant &value, bool *ok) 313 { 314 int val = 0; 315 316 Q_ASSERT(c); 317 Q_ASSERT(ok); 318 Q_UNUSED(params) 319 320 if (value.userType() == QMetaType::QString) { 321 const QString field = value.toString(); 322 /* if (params.contains(field)) { 323 const QString _val = params.value(field); 324 val = _val.toInt(ok); 325 // if (!*ok) { 326 // val = c->locale().toInt(_val, ok); 327 // } 328 } else*/ if (c->stash().contains(field)) { 329 val = c->stash(field).toInt(ok); 330 } else { 331 *ok = false; 332 } 333 } else { 334 val = value.toInt(ok); 335 } 336 337 return val; 338 } 339 valueToNumber(Context * c,const QString & value,QMetaType::Type type)340 static QVariant valueToNumber(Context *c, const QString &value, QMetaType::Type type) 341 { 342 QVariant var; 343 344 Q_UNUSED(c) 345 346 bool ok = false; 347 348 switch (type) { 349 case QMetaType::Char: 350 { 351 const short _v = value.toShort(&ok); 352 if (ok) { 353 if ((_v < static_cast<short>(std::numeric_limits<char>::max())) && (_v > static_cast<short>(std::numeric_limits<char>::min()))) { 354 var.setValue<char>(static_cast<char>(_v)); 355 } 356 } 357 } 358 break; 359 case QMetaType::Short: 360 { 361 // const short v = c->locale().toShort(value, &ok); 362 const short v = value.toShort(&ok); 363 if (ok) { 364 var.setValue(v); 365 } 366 } 367 break; 368 case QMetaType::Int: 369 { 370 // const int v = c->locale().toInt(value, &ok); 371 const int v = value.toInt(&ok); 372 if (ok) { 373 var.setValue(v); 374 } 375 } 376 break; 377 case QMetaType::Long: 378 { 379 const long v = value.toLong(&ok); 380 if (ok) { 381 var.setValue(v); 382 } 383 } 384 break; 385 case QMetaType::LongLong: 386 { 387 // const qlonglong v = c->locale().toLongLong(value, &ok); 388 // if (ok) { 389 // if (type == QMetaType::Long) { 390 // if (v < static_cast<qlonglong>(std::numeric_limits<long>::max())) { 391 // var.setValue<long>(static_cast<long>(v)); 392 // } 393 // } else { 394 // var.setValue<qlonglong>(v); 395 // } 396 // } 397 const qlonglong v = value.toLongLong(&ok); 398 if (ok) { 399 var.setValue(v); 400 } 401 } 402 break; 403 case QMetaType::UChar: 404 { 405 const ushort _v = value.toUShort(&ok); 406 if (ok) { 407 if ((_v < static_cast<ushort>(std::numeric_limits<uchar>::max())) && (_v > static_cast<ushort>(std::numeric_limits<uchar>::min()))) { 408 var.setValue<uchar>(static_cast<uchar>(_v)); 409 } 410 } 411 } 412 break; 413 case QMetaType::UShort: 414 { 415 // const ushort v = c->locale().toUShort(value, &ok); 416 const ushort v = value.toUShort(&ok); 417 if (ok) { 418 var.setValue(v); 419 } 420 } 421 break; 422 case QMetaType::UInt: 423 { 424 // const uint v = c->locale().toUInt(value, &ok); 425 const uint v = value.toUInt(&ok); 426 if (ok) { 427 var.setValue(v); 428 } 429 } 430 break; 431 case QMetaType::ULong: 432 { 433 const ulong v = value.toULong(&ok); 434 if (ok) { 435 var.setValue(v); 436 } 437 } 438 break; 439 case QMetaType::ULongLong: 440 { 441 // const qulonglong v = c->locale().toULongLong(value, &ok); 442 // if (ok) { 443 // if (type == QMetaType::ULong) { 444 // if ((v > static_cast<qulonglong>(std::numeric_limits<ulong>::min())) && (v < static_cast<qulonglong>(std::numeric_limits<ulong>::max()))) { 445 // var.setValue<ulong>(static_cast<ulong>(v)); 446 // } 447 // } else { 448 // var.setValue<qulonglong>(v); 449 // } 450 // } 451 const qulonglong v = value.toULongLong(&ok); 452 if (ok) { 453 var.setValue(v); 454 } 455 } 456 break; 457 case QMetaType::Float: 458 { 459 // const float v = c->locale().toFloat(value, &ok); 460 const float v = value.toFloat(&ok); 461 if (ok) { 462 var.setValue(v); 463 } 464 } 465 break; 466 case QMetaType::Double: 467 { 468 // const double v = c->locale().toDouble(value, &ok); 469 const double v = value.toDouble(&ok); 470 if (ok) { 471 var.setValue(v); 472 } 473 } 474 break; 475 default: 476 break; 477 } 478 479 return var; 480 } 481 482 QLatin1String translationContext; 483 QString field; 484 QString defValKey; 485 ValidatorMessages messages; 486 bool trimBefore = true; 487 }; 488 489 } 490 491 #endif //CUTELYSTVALIDATORRULE_P_H 492 493