* Validate brackets once parsing ends. * @return @c false if matching brackets fails. * @note Validation is destructive, that is, it transitions this object into an undefined state. */
| 144 | * @note Validation is destructive, that is, it transitions this object into an undefined state. |
| 145 | */ |
| 146 | bool validate() |
| 147 | { |
| 148 | // Inserted opening brackets normally match inserted closing brackets. Same for removed brackets. |
| 149 | // In addition, inserted opening brackets match removed opening brackets. Same for closing brackets. |
| 150 | // An inserted-removed match can mean that an unformatted-formatted text matcher misinterpreted the formatter's |
| 151 | // intention (other fuzzy characters could actually be inserted or removed near the untouched bracket). |
| 152 | // Such a misinterpretation is not a problem at all thanks to the inserted-removed match. |
| 153 | |
| 154 | // We move backwards, so closing brackets must be encountered before the matching open brackets. |
| 155 | int closingBracketCount = 0; |
| 156 | for (int i = m_data.size() - 1; i >= 0; --i) { |
| 157 | auto p = m_data.at(i); |
| 158 | Q_ASSERT(p.count != 0); |
| 159 | |
| 160 | if (p.isOpening) { |
| 161 | if ((closingBracketCount > 0) != (p.count > 0)) { |
| 162 | // Insertion/removal mismatch of opening and closing brackets. When a closing bracket is |
| 163 | // inserted and an opening bracket is removed (or vice versa), they clearly cannot match. |
| 164 | return false; |
| 165 | } |
| 166 | if (std::abs(closingBracketCount) < std::abs(p.count)) { |
| 167 | return false; // not enough closing brackets to match all opening brackets |
| 168 | } |
| 169 | closingBracketCount -= p.count; |
| 170 | } else { |
| 171 | closingBracketCount += p.count; |
| 172 | } |
| 173 | } |
| 174 | return closingBracketCount == 0; // are all closing brackets matched by opening brackets? |
| 175 | } |
| 176 | |
| 177 | private: |
| 178 | struct BracketSequence |
no test coverage detected