Maybe parses a Unicode character group like \p{Han} or \P{Han} (the latter is a negated group).
| 1728 | // Maybe parses a Unicode character group like \p{Han} or \P{Han} |
| 1729 | // (the latter is a negated group). |
| 1730 | ParseStatus ParseUnicodeGroup(StringPiece* s, Regexp::ParseFlags parse_flags, |
| 1731 | CharClassBuilder *cc, |
| 1732 | RegexpStatus* status) { |
| 1733 | // Decide whether to parse. |
| 1734 | if (!(parse_flags & Regexp::UnicodeGroups)) |
| 1735 | return kParseNothing; |
| 1736 | if (s->size() < 2 || (*s)[0] != '\\') |
| 1737 | return kParseNothing; |
| 1738 | Rune c = (*s)[1]; |
| 1739 | if (c != 'p' && c != 'P') |
| 1740 | return kParseNothing; |
| 1741 | |
| 1742 | // Committed to parse. Results: |
| 1743 | int sign = +1; // -1 = negated char class |
| 1744 | if (c == 'P') |
| 1745 | sign = -sign; |
| 1746 | StringPiece seq = *s; // \p{Han} or \pL |
| 1747 | StringPiece name; // Han or L |
| 1748 | s->remove_prefix(2); // '\\', 'p' |
| 1749 | |
| 1750 | if (!StringPieceToRune(&c, s, status)) |
| 1751 | return kParseError; |
| 1752 | if (c != '{') { |
| 1753 | // Name is the bit of string we just skipped over for c. |
| 1754 | const char* p = seq.data() + 2; |
| 1755 | name = StringPiece(p, static_cast<size_t>(s->data() - p)); |
| 1756 | } else { |
| 1757 | // Name is in braces. Look for closing } |
| 1758 | size_t end = s->find('}', 0); |
| 1759 | if (end == StringPiece::npos) { |
| 1760 | if (!IsValidUTF8(seq, status)) |
| 1761 | return kParseError; |
| 1762 | status->set_code(kRegexpBadCharRange); |
| 1763 | status->set_error_arg(seq); |
| 1764 | return kParseError; |
| 1765 | } |
| 1766 | name = StringPiece(s->data(), end); // without '}' |
| 1767 | s->remove_prefix(end + 1); // with '}' |
| 1768 | if (!IsValidUTF8(name, status)) |
| 1769 | return kParseError; |
| 1770 | } |
| 1771 | |
| 1772 | // Chop seq where s now begins. |
| 1773 | seq = StringPiece(seq.data(), static_cast<size_t>(s->data() - seq.data())); |
| 1774 | |
| 1775 | if (!name.empty() && name[0] == '^') { |
| 1776 | sign = -sign; |
| 1777 | name.remove_prefix(1); // '^' |
| 1778 | } |
| 1779 | |
| 1780 | #if !defined(RE2_USE_ICU) |
| 1781 | // Look up the group in the RE2 Unicode data. |
| 1782 | const UGroup *g = LookupUnicodeGroup(name); |
| 1783 | if (g == NULL) { |
| 1784 | status->set_code(kRegexpBadCharRange); |
| 1785 | status->set_error_arg(seq); |
| 1786 | return kParseError; |
| 1787 | } |
no test coverage detected