File indexing completed on 2024-12-22 04:59:46

0001 /*
0002     SPDX-FileCopyrightText: 2018-2023 Volker Krause <vkrause@kde.org>
0003     SPDX-License-Identifier: LGPL-2.0-or-later
0004 */
0005 
0006 #include "tickettokencomparator_p.h"
0007 #include "compare-logging.h"
0008 
0009 #include "uic9183/uic9183block.h"
0010 #include "uic9183/uic9183header.h"
0011 #include "uic9183/uic9183parser.h"
0012 
0013 #include <cstring>
0014 
0015 using namespace KItinerary;
0016 
0017 /** Checks that @p lhs and @p rhs have a different prefix is they are both set. */
0018 static bool prefixConflictIfPresent(const QString &lhs, const QString &rhs, Qt::CaseSensitivity caseSensitive = Qt::CaseSensitive)
0019 {
0020     return !lhs.isEmpty() && !rhs.isEmpty() && !lhs.startsWith(rhs, caseSensitive) && !rhs.startsWith(lhs, caseSensitive);
0021 }
0022 static bool prefixConflictIfPresent(const QByteArray &lhs, const QByteArray &rhs)
0023 {
0024     return !lhs.isEmpty() && !rhs.isEmpty() && !lhs.startsWith(rhs) && !rhs.startsWith(lhs);
0025 }
0026 
0027 static bool isUicBlockSubset(const Uic9183Parser &lhs, const Uic9183Parser &rhs)
0028 {
0029     for (auto block = lhs.firstBlock(); !block.isNull(); block = block.nextBlock()) {
0030         // ignore 0080VU blocks, those change in DB online tickets on every retrieval
0031         if (std::strncmp(block.name(), "0080VU", 6) == 0) {
0032             continue;
0033         }
0034         const auto rhsBlock = rhs.findBlock(block.name());
0035         if (rhsBlock.isNull() || rhsBlock != block) {
0036             return false;
0037         }
0038     }
0039     return true;
0040 }
0041 
0042 static bool compareUic918Token(const QByteArray &lhs, const QByteArray &rhs)
0043 {
0044     if (!Uic9183Parser::maybeUic9183(lhs) || !Uic9183Parser::maybeUic9183(rhs)) {
0045         return false;
0046     }
0047 
0048     Uic9183Parser lhsUic;
0049     lhsUic.parse(lhs);
0050     Uic9183Parser rhsUic;
0051     rhsUic.parse(rhs);
0052     if (!lhsUic.isValid() || !rhsUic.isValid()) {
0053         return false;
0054     }
0055 
0056     return lhsUic.header() == rhsUic.header() && isUicBlockSubset(lhsUic, rhsUic) && isUicBlockSubset(rhsUic, lhsUic);
0057 }
0058 
0059 bool KItinerary::TicketTokenComparator::isSame(const QVariant &lhs, const QVariant &rhs)
0060 {
0061     if (lhs.isNull() || rhs.isNull()) {
0062         return true;
0063     }
0064     if (lhs.userType() != rhs.userType()) {
0065         return false;
0066     }
0067 
0068     if (lhs.userType() == QMetaType::QString) {
0069         return !prefixConflictIfPresent(lhs.toString(), rhs.toString(), Qt::CaseInsensitive);
0070     }
0071     if (lhs.userType() == QMetaType::QByteArray) {
0072         const auto lhsBA = lhs.toByteArray();
0073         const auto rhsBA = rhs.toByteArray();
0074         if (!prefixConflictIfPresent(lhsBA, rhsBA)) {
0075             return true;
0076         }
0077 
0078         return compareUic918Token(lhsBA, rhsBA);
0079     }
0080 
0081     qCWarning(CompareLog) << "unhandled ticket token type" << lhs << rhs;
0082     return false;
0083 }