| 11734 | |
| 11735 | |
| 11736 | ResultType RegExMatchObject::Create(LPCTSTR aHaystack, int *aOffset, LPCTSTR *aPatternName |
| 11737 | , int aPatternCount, int aCapturedPatternCount, LPCTSTR aMark, IObject *&aNewObject) |
| 11738 | { |
| 11739 | aNewObject = NULL; |
| 11740 | |
| 11741 | // If there was no match, seems best to not return an object: |
| 11742 | if (aCapturedPatternCount < 1) |
| 11743 | return OK; |
| 11744 | |
| 11745 | RegExMatchObject *m = new RegExMatchObject(); |
| 11746 | if (!m) |
| 11747 | return FAIL; |
| 11748 | m->SetBase(sPrototype); |
| 11749 | |
| 11750 | if ( aMark && !(m->mMark = _tcsdup(aMark)) ) |
| 11751 | { |
| 11752 | m->Release(); |
| 11753 | return FAIL; |
| 11754 | } |
| 11755 | |
| 11756 | ASSERT(aCapturedPatternCount >= 1); |
| 11757 | ASSERT(aPatternCount >= aCapturedPatternCount); |
| 11758 | |
| 11759 | // Use aPatternCount vs aCapturedPatternCount since we want to be able to retrieve the |
| 11760 | // names of *all* subpatterns, even ones that weren't captured. For instance, a loop |
| 11761 | // converting the object to an old-style pseudo-array would need to initialize even the |
| 11762 | // array items that weren't captured. |
| 11763 | m->mPatternCount = aPatternCount; |
| 11764 | |
| 11765 | // Allocate memory for a copy of the offset array. |
| 11766 | if ( !(m->mOffset = (int *)malloc(aPatternCount * 2 * sizeof(int *))) ) |
| 11767 | { |
| 11768 | m->Release(); |
| 11769 | return FAIL; |
| 11770 | } |
| 11771 | // memcpy currently benchmarks slightly faster on x64 than copying offsets in the loop below: |
| 11772 | memcpy(m->mOffset, aOffset, aPatternCount * 2 * sizeof(int)); |
| 11773 | |
| 11774 | // Do some pre-processing: |
| 11775 | // - Locate the smallest portion of haystack that contains all matches. |
| 11776 | // - Convert end offsets to lengths. |
| 11777 | int p, min_offset = INT_MAX, max_offset = -1; |
| 11778 | for (p = 0; p < aCapturedPatternCount; ++p) |
| 11779 | { |
| 11780 | if (m->mOffset[p*2] > -1) |
| 11781 | { |
| 11782 | // Substring is non-empty, so ensure we copy this portion of haystack. |
| 11783 | if (min_offset > m->mOffset[p*2]) |
| 11784 | min_offset = m->mOffset[p*2]; |
| 11785 | if (max_offset < m->mOffset[p*2+1]) |
| 11786 | max_offset = m->mOffset[p*2+1]; |
| 11787 | } |
| 11788 | // Convert end offset to length. |
| 11789 | m->mOffset[p*2+1] -= m->mOffset[p*2]; |
| 11790 | } |
| 11791 | // Initialize the remainder of the offset vector (patterns which were not captured), |
| 11792 | // which have indeterminate values if we're called by a regex callout and therefore |
| 11793 | // can't be handled the same way as in the loop above. |