@@ -1848,6 +1848,29 @@ SRE(search)(SRE_STATE* state, SRE_CODE* pattern)
18481848 ptr ++ ;
18491849 RESET_CAPTURE_GROUP ();
18501850 }
1851+ } else if (pattern [0 ] == SRE_OP_AT &&
1852+ pattern [1 ] == SRE_AT_BEGINNING_LINE ) {
1853+ /* pattern is anchored at the start of a line (MULTILINE "^").
1854+ Only the start of the string and the character after a linebreak
1855+ can match, so jump from one line start to the next instead of
1856+ trying SRE(match) at every position. */
1857+ end = (SRE_CHAR * )state -> end ;
1858+ TRACE (("|%p|%p|SEARCH AT_BEGINNING_LINE\n" , pattern , ptr ));
1859+ state -> start = state -> ptr = ptr ;
1860+ status = SRE (match )(state , pattern , 1 );
1861+ state -> must_advance = 0 ;
1862+ while (status == 0 ) {
1863+ /* skip to the next linebreak ... */
1864+ while (ptr < end && !SRE_IS_LINEBREAK ((int ) * ptr ))
1865+ ptr ++ ;
1866+ if (ptr >= end )
1867+ return 0 ;
1868+ ptr ++ ; /* ... and step past it, onto a line start */
1869+ RESET_CAPTURE_GROUP ();
1870+ TRACE (("|%p|%p|SEARCH AT_BEGINNING_LINE\n" , pattern , ptr ));
1871+ state -> start = state -> ptr = ptr ;
1872+ status = SRE (match )(state , pattern , 0 );
1873+ }
18511874 } else {
18521875 /* general case */
18531876 assert (ptr <= end );
@@ -1863,19 +1886,6 @@ SRE(search)(SRE_STATE* state, SRE_CODE* pattern)
18631886 return 0 ;
18641887 }
18651888 while (status == 0 && ptr < end ) {
1866- if (pattern [0 ] == SRE_OP_AT &&
1867- pattern [1 ] == SRE_AT_BEGINNING_LINE &&
1868- (void * ) ptr > state -> beginning &&
1869- !SRE_IS_LINEBREAK ((int ) ptr [-1 ]))
1870- {
1871- /* fast-forward to the next newline character */
1872- while (ptr < end && !SRE_IS_LINEBREAK ((int ) * ptr )) {
1873- ptr ++ ;
1874- }
1875- if (ptr >= end ) {
1876- return 0 ;
1877- }
1878- }
18791889 ptr ++ ;
18801890 RESET_CAPTURE_GROUP ();
18811891 TRACE (("|%p|%p|SEARCH\n" , pattern , ptr ));
0 commit comments