File indexing completed on 2024-04-28 09:47:02
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 }