| 1616 | } |
| 1617 | |
| 1618 | QVector<QString> SearchReplaceWidget::capturePatterns(const QString& pattern) const { |
| 1619 | QVector<QString> capturePatterns; |
| 1620 | capturePatterns.reserve(9); |
| 1621 | QStack<ParInfo> parInfos; |
| 1622 | |
| 1623 | const int inputLen = pattern.length(); |
| 1624 | int input = 0; // walker index |
| 1625 | bool insideClass = false; |
| 1626 | int captureCount = 0; |
| 1627 | |
| 1628 | while (input < inputLen) { |
| 1629 | if (insideClass) { |
| 1630 | // Wait for closing, unescaped ']' |
| 1631 | if (pattern[input].unicode() == L']') |
| 1632 | insideClass = false; |
| 1633 | |
| 1634 | input++; |
| 1635 | } else { |
| 1636 | switch (pattern[input].unicode()) { |
| 1637 | case L'\\': |
| 1638 | // Skip this and any next character |
| 1639 | input += 2; |
| 1640 | break; |
| 1641 | |
| 1642 | case L'(': |
| 1643 | ParInfo curInfo; |
| 1644 | curInfo.openIndex = input; |
| 1645 | curInfo.capturing = (input + 1 >= inputLen) || (pattern[input + 1].unicode() != '?'); |
| 1646 | if (curInfo.capturing) { |
| 1647 | captureCount++; |
| 1648 | } |
| 1649 | curInfo.captureNumber = captureCount; |
| 1650 | parInfos.push(curInfo); |
| 1651 | |
| 1652 | input++; |
| 1653 | break; |
| 1654 | |
| 1655 | case L')': |
| 1656 | if (!parInfos.empty()) { |
| 1657 | ParInfo& top = parInfos.top(); |
| 1658 | if (top.capturing && (top.captureNumber <= 9)) { |
| 1659 | const int start = top.openIndex + 1; |
| 1660 | const int len = input - start; |
| 1661 | if (capturePatterns.size() < top.captureNumber) { |
| 1662 | capturePatterns.resize(top.captureNumber); |
| 1663 | } |
| 1664 | capturePatterns[top.captureNumber - 1] = pattern.mid(start, len); |
| 1665 | } |
| 1666 | parInfos.pop(); |
| 1667 | } |
| 1668 | |
| 1669 | input++; |
| 1670 | break; |
| 1671 | |
| 1672 | case L'[': |
| 1673 | input++; |
| 1674 | insideClass = true; |
| 1675 | break; |