File indexing completed on 2024-04-21 05:51:36

0001 /*
0002  *  SPDX-FileCopyrightText: 2002-2003 Jesper K. Pedersen <blackie@kde.org>
0003  *
0004  *  SPDX-License-Identifier: LGPL-2.0-only
0005  **/
0006 
0007 #include "concregexp.h"
0008 
0009 #include "compoundregexp.h"
0010 #include "widgetfactory.h"
0011 
0012 ConcRegExp::ConcRegExp(bool selected)
0013     : RegExp(selected)
0014 {
0015 }
0016 
0017 void ConcRegExp::addRegExp(RegExp *regExp)
0018 {
0019     list.append(regExp);
0020     addChild(regExp);
0021 }
0022 
0023 RegExpList ConcRegExp::children()
0024 {
0025     return list;
0026 }
0027 
0028 bool ConcRegExp::check(ErrorMap &map, bool first, bool last)
0029 {
0030     bool f = first;
0031     bool possibleEmpty = true;
0032     RegExpListIt it(list);
0033     while (it.hasNext()) {
0034         possibleEmpty = it.next()->check(map, f, last && !it.hasNext()) && possibleEmpty;
0035         if (!possibleEmpty) {
0036             f = false;
0037         }
0038     }
0039     return possibleEmpty;
0040 }
0041 
0042 RegExp *ConcRegExp::lastRegExp()
0043 {
0044     if (list.isEmpty()) {
0045         return nullptr;
0046     } else {
0047         return list.at(list.count() - 1);
0048     }
0049 }
0050 
0051 QDomNode ConcRegExp::toXml(QDomDocument *doc) const
0052 {
0053     QDomElement top = doc->createElement(QStringLiteral("Concatenation"));
0054     for (RegExp *r : std::as_const(list)) {
0055         top.appendChild(r->toXml(doc));
0056     }
0057     return top;
0058 }
0059 
0060 bool ConcRegExp::load(const QDomElement &top, const QString &version)
0061 {
0062     Q_ASSERT(top.tagName() == QStringLiteral("Concatenation"));
0063 
0064     for (QDomNode child = top.firstChild(); !child.isNull(); child = child.nextSibling()) {
0065         if (!child.isElement()) {
0066             continue; // User might have added a comment.
0067         }
0068 
0069         RegExp *regexp = WidgetFactory::createRegExp(child.toElement(), version);
0070         if (regexp == nullptr) {
0071             return false;
0072         }
0073         addRegExp(regexp);
0074     }
0075     return true;
0076 }
0077 
0078 bool ConcRegExp::operator==(const RegExp &other) const
0079 {
0080     // TODO: Merge with AltnRegExp::operator==
0081     if (list.count() == 1) {
0082         return other == *(const_cast<QList<RegExp *> &>(list).at(0));
0083     }
0084 
0085     if (other.type() != type()) {
0086         return false;
0087     }
0088 
0089     const ConcRegExp &theOther = dynamic_cast<const ConcRegExp &>(other);
0090 
0091     if (list.count() != theOther.list.count()) {
0092         return false;
0093     }
0094 
0095     RegExpListIt it1(list);
0096     RegExpListIt it2(theOther.list);
0097 
0098     while (it1.hasNext() && it2.hasNext()) {
0099         if (!(it1.next() == it2.next())) {
0100             return false;
0101         }
0102     }
0103     return true;
0104 }
0105 
0106 void ConcRegExp::replacePart(CompoundRegExp *replacement)
0107 {
0108     RegExp *otherChild = replacement->child();
0109     ConcRegExp *otherConc = dynamic_cast<ConcRegExp *>(otherChild);
0110     if (!otherConc) {
0111         // Watch out for garbage here!
0112         otherConc = new ConcRegExp(false);
0113         otherConc->addRegExp(otherChild);
0114     }
0115 
0116     RegExpList newList;
0117     RegExpListStlIt it1(list.begin());
0118     while (it1 != list.end()) {
0119         (*it1)->replacePart(replacement);
0120         RegExpListStlIt it2 = it1;
0121         RegExpListStlIt it3(otherConc->list.begin());
0122         bool match = true;
0123         int count = 0;
0124 
0125         // See if replacement is a sublist of list starting from what it1 points at
0126         for (; it2 != list.end() && it3 != otherConc->list.end() && match;) {
0127             if (!(**it2 == **it3)) {
0128                 match = false;
0129             }
0130             ++it2;
0131             ++it3;
0132             ++count;
0133         }
0134 
0135         if (match && it3 == otherConc->list.end()) {
0136             // I found a match, delete the element in it1, which is common with it3
0137             while (*it1 != *it2) {
0138                 RegExp *item = *it1;
0139                 ++it1;
0140                 delete item;
0141             }
0142             RegExp *theClone = replacement->clone();
0143             newList.append(theClone);
0144             addChild(theClone);
0145         } else {
0146             newList.append(*it1);
0147             ++it1;
0148         }
0149     }
0150     list = newList;
0151 }